Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'sunxi-drm-for-4.10' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into drm-next

sun4i-drm changes for 4.10

Support for the Allwinner A31 SoC display engine using the sun4i-drm
driver.

* tag 'sunxi-drm-for-4.10' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux:
drm/sun4i: Add a few formats
drm/sun4i: Add compatible strings for A31/A31s display pipelines
drm/sun4i: Add compatible string for A31/A31s TCON (timing controller)
drm/sun4i: tcon: Move SoC specific quirks to a DT matched data structure
drm/sun4i: sun6i-drc: Support DRC on A31 and A31s

+78 -20
+9 -1
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
··· 28 28 Required properties: 29 29 - compatible: value must be either: 30 30 * allwinner,sun5i-a13-tcon 31 + * allwinner,sun6i-a31-tcon 32 + * allwinner,sun6i-a31s-tcon 31 33 * allwinner,sun8i-a33-tcon 32 34 - reg: base address and size of memory-mapped region 33 35 - interrupts: interrupt associated to this IP ··· 52 50 second the block connected to the TCON channel 1 (usually the TV 53 51 encoder) 54 52 55 - On the A13, there is one more clock required: 53 + On SoCs other than the A33, there is one more clock required: 56 54 - 'tcon-ch1': The clock driving the TCON channel 1 57 55 58 56 DRC ··· 66 64 67 65 Required properties: 68 66 - compatible: value must be one of: 67 + * allwinner,sun6i-a31-drc 68 + * allwinner,sun6i-a31s-drc 69 69 * allwinner,sun8i-a33-drc 70 70 - reg: base address and size of the memory-mapped region. 71 71 - interrupts: interrupt associated to this IP ··· 91 87 Required properties: 92 88 - compatible: value must be one of: 93 89 * allwinner,sun5i-a13-display-backend 90 + * allwinner,sun6i-a31-display-backend 94 91 * allwinner,sun8i-a33-display-backend 95 92 - reg: base address and size of the memory-mapped region. 96 93 - clocks: phandles to the clocks feeding the frontend and backend ··· 122 117 Required properties: 123 118 - compatible: value must be one of: 124 119 * allwinner,sun5i-a13-display-frontend 120 + * allwinner,sun6i-a31-display-frontend 125 121 * allwinner,sun8i-a33-display-frontend 126 122 - reg: base address and size of the memory-mapped region. 127 123 - interrupts: interrupt associated to this IP ··· 148 142 Required properties: 149 143 - compatible: value must be one of: 150 144 * allwinner,sun5i-a13-display-engine 145 + * allwinner,sun6i-a31-display-engine 146 + * allwinner,sun6i-a31s-display-engine 151 147 * allwinner,sun8i-a33-display-engine 152 148 153 149 - allwinner,pipelines: list of phandle to the display engine
+21
drivers/gpu/drm/sun4i/sun4i_backend.c
··· 95 95 *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888; 96 96 break; 97 97 98 + case DRM_FORMAT_ARGB4444: 99 + *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB4444; 100 + break; 101 + 102 + case DRM_FORMAT_ARGB1555: 103 + *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB1555; 104 + break; 105 + 106 + case DRM_FORMAT_RGBA5551: 107 + *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA5551; 108 + break; 109 + 110 + case DRM_FORMAT_RGBA4444: 111 + *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA4444; 112 + break; 113 + 98 114 case DRM_FORMAT_XRGB8888: 99 115 *mode = SUN4I_BACKEND_LAY_FBFMT_XRGB8888; 100 116 break; 101 117 102 118 case DRM_FORMAT_RGB888: 103 119 *mode = SUN4I_BACKEND_LAY_FBFMT_RGB888; 120 + break; 121 + 122 + case DRM_FORMAT_RGB565: 123 + *mode = SUN4I_BACKEND_LAY_FBFMT_RGB565; 104 124 break; 105 125 106 126 default: ··· 428 408 429 409 static const struct of_device_id sun4i_backend_of_table[] = { 430 410 { .compatible = "allwinner,sun5i-a13-display-backend" }, 411 + { .compatible = "allwinner,sun6i-a31-display-backend" }, 431 412 { .compatible = "allwinner,sun8i-a33-display-backend" }, 432 413 { } 433 414 };
+5
drivers/gpu/drm/sun4i/sun4i_drv.c
··· 200 200 static bool sun4i_drv_node_is_frontend(struct device_node *node) 201 201 { 202 202 return of_device_is_compatible(node, "allwinner,sun5i-a13-display-frontend") || 203 + of_device_is_compatible(node, "allwinner,sun6i-a31-display-frontend") || 203 204 of_device_is_compatible(node, "allwinner,sun8i-a33-display-frontend"); 204 205 } 205 206 206 207 static bool sun4i_drv_node_is_tcon(struct device_node *node) 207 208 { 208 209 return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") || 210 + of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") || 211 + of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") || 209 212 of_device_is_compatible(node, "allwinner,sun8i-a33-tcon"); 210 213 } 211 214 ··· 324 321 325 322 static const struct of_device_id sun4i_drv_of_table[] = { 326 323 { .compatible = "allwinner,sun5i-a13-display-engine" }, 324 + { .compatible = "allwinner,sun6i-a31-display-engine" }, 325 + { .compatible = "allwinner,sun6i-a31s-display-engine" }, 327 326 { .compatible = "allwinner,sun8i-a33-display-engine" }, 328 327 { } 329 328 };
+6
drivers/gpu/drm/sun4i/sun4i_layer.c
··· 73 73 static const uint32_t sun4i_backend_layer_formats_primary[] = { 74 74 DRM_FORMAT_ARGB8888, 75 75 DRM_FORMAT_RGB888, 76 + DRM_FORMAT_RGB565, 76 77 DRM_FORMAT_XRGB8888, 77 78 }; 78 79 79 80 static const uint32_t sun4i_backend_layer_formats_overlay[] = { 80 81 DRM_FORMAT_ARGB8888, 82 + DRM_FORMAT_ARGB4444, 83 + DRM_FORMAT_ARGB1555, 84 + DRM_FORMAT_RGBA5551, 85 + DRM_FORMAT_RGBA4444, 81 86 DRM_FORMAT_RGB888, 87 + DRM_FORMAT_RGB565, 82 88 DRM_FORMAT_XRGB8888, 83 89 }; 84 90
+28 -15
drivers/gpu/drm/sun4i/sun4i_tcon.c
··· 20 20 #include <linux/component.h> 21 21 #include <linux/ioport.h> 22 22 #include <linux/of_address.h> 23 + #include <linux/of_device.h> 23 24 #include <linux/of_graph.h> 24 25 #include <linux/of_irq.h> 25 26 #include <linux/regmap.h> ··· 63 62 return; 64 63 } 65 64 66 - WARN_ON(!tcon->has_channel_1); 65 + WARN_ON(!tcon->quirks->has_channel_1); 67 66 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 68 67 SUN4I_TCON1_CTL_TCON_ENABLE, 0); 69 68 clk_disable_unprepare(tcon->sclk1); ··· 81 80 return; 82 81 } 83 82 84 - WARN_ON(!tcon->has_channel_1); 83 + WARN_ON(!tcon->quirks->has_channel_1); 85 84 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 86 85 SUN4I_TCON1_CTL_TCON_ENABLE, 87 86 SUN4I_TCON1_CTL_TCON_ENABLE); ··· 203 202 u8 clk_delay; 204 203 u32 val; 205 204 206 - WARN_ON(!tcon->has_channel_1); 205 + WARN_ON(!tcon->quirks->has_channel_1); 207 206 208 207 /* Adjust clock delay */ 209 208 clk_delay = sun4i_tcon_get_clk_delay(mode, 1); ··· 267 266 /* 268 267 * FIXME: Undocumented bits 269 268 */ 270 - if (tcon->has_mux) 269 + if (tcon->quirks->has_unknown_mux) 271 270 regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, 1); 272 271 } 273 272 EXPORT_SYMBOL(sun4i_tcon1_mode_set); ··· 328 327 return PTR_ERR(tcon->sclk0); 329 328 } 330 329 331 - if (tcon->has_channel_1) { 330 + if (tcon->quirks->has_channel_1) { 332 331 tcon->sclk1 = devm_clk_get(dev, "tcon-ch1"); 333 332 if (IS_ERR(tcon->sclk1)) { 334 333 dev_err(dev, "Couldn't get the TCON channel 1 clock\n"); ··· 488 487 drv->tcon = tcon; 489 488 tcon->drm = drm; 490 489 tcon->dev = dev; 491 - 492 - if (of_device_is_compatible(dev->of_node, "allwinner,sun5i-a13-tcon")) { 493 - tcon->has_mux = true; 494 - tcon->has_channel_1 = true; 495 - } else { 496 - tcon->has_mux = false; 497 - tcon->has_channel_1 = false; 498 - } 490 + tcon->quirks = of_device_get_match_data(dev); 499 491 500 492 tcon->lcd_rst = devm_reset_control_get(dev, "lcd"); 501 493 if (IS_ERR(tcon->lcd_rst)) { ··· 582 588 return 0; 583 589 } 584 590 591 + static const struct sun4i_tcon_quirks sun5i_a13_quirks = { 592 + .has_unknown_mux = true, 593 + .has_channel_1 = true, 594 + }; 595 + 596 + static const struct sun4i_tcon_quirks sun6i_a31_quirks = { 597 + .has_channel_1 = true, 598 + }; 599 + 600 + static const struct sun4i_tcon_quirks sun6i_a31s_quirks = { 601 + .has_channel_1 = true, 602 + }; 603 + 604 + static const struct sun4i_tcon_quirks sun8i_a33_quirks = { 605 + /* nothing is supported */ 606 + }; 607 + 585 608 static const struct of_device_id sun4i_tcon_of_table[] = { 586 - { .compatible = "allwinner,sun5i-a13-tcon" }, 587 - { .compatible = "allwinner,sun8i-a33-tcon" }, 609 + { .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks }, 610 + { .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks }, 611 + { .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks }, 612 + { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks }, 588 613 { } 589 614 }; 590 615 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
+7 -4
drivers/gpu/drm/sun4i/sun4i_tcon.h
··· 142 142 143 143 #define SUN4I_TCON_MAX_CHANNELS 2 144 144 145 + struct sun4i_tcon_quirks { 146 + bool has_unknown_mux; /* sun5i has undocumented mux */ 147 + bool has_channel_1; /* a33 does not have channel 1 */ 148 + }; 149 + 145 150 struct sun4i_tcon { 146 151 struct device *dev; 147 152 struct drm_device *drm; ··· 165 160 /* Reset control */ 166 161 struct reset_control *lcd_rst; 167 162 168 - /* Platform adjustments */ 169 - bool has_mux; 170 - 171 163 struct drm_panel *panel; 172 164 173 - bool has_channel_1; 165 + /* Platform adjustments */ 166 + const struct sun4i_tcon_quirks *quirks; 174 167 }; 175 168 176 169 struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
+2
drivers/gpu/drm/sun4i/sun6i_drc.c
··· 98 98 } 99 99 100 100 static const struct of_device_id sun6i_drc_of_table[] = { 101 + { .compatible = "allwinner,sun6i-a31-drc" }, 102 + { .compatible = "allwinner,sun6i-a31s-drc" }, 101 103 { .compatible = "allwinner,sun8i-a33-drc" }, 102 104 { } 103 105 };