diff options
author | Dave Airlie <airlied@redhat.com> | 2014-04-05 02:12:27 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-04-05 02:12:27 -0400 |
commit | 243b930f8b228428c2a14ebbb09045041ed0bc70 (patch) | |
tree | 5bd5d87efba1a5394af4a13f85b94703fa8efc31 /drivers/gpu/drm/panel | |
parent | 13b938927412db95274a045aacadf310e6a30acb (diff) | |
parent | 712ac1ba63448d38e2fc3f2b58e62ca4af9778c2 (diff) |
Merge tag 'drm/panel/for-3.15-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm/panel: Changes for v3.15-rc1
Add support for a couple more simple panels. A few cleanups to the
simple panel driver are also included (gpiod interface conversion,
removal of redundant call to regulator_disable()).
* tag 'drm/panel/for-3.15-rc1' of git://anongit.freedesktop.org/tegra/linux:
drm/panel: add support for LG LD070WX3-SL01 panel
drm/panel: add support for LG LH500WX1-SD03 panel
drm/panel: simple: Allow DSI panels to provide mode flags
drm/panel: simple: Allow GPIO accesses to sleep
drm/panel: remove redundant regulator_disable()
drm/panel: use gpiod interface for enable GPIO
drm/panel: Add LG 12.9" LCD panel
MAINTAINERS: Add entry for DRM panel drivers
Conflicts:
MAINTAINERS
Diffstat (limited to 'drivers/gpu/drm/panel')
-rw-r--r-- | drivers/gpu/drm/panel/panel-simple.c | 157 |
1 files changed, 106 insertions, 51 deletions
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 59d52ca2c67f..309f29e9234a 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c | |||
@@ -22,9 +22,8 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/backlight.h> | 24 | #include <linux/backlight.h> |
25 | #include <linux/gpio.h> | 25 | #include <linux/gpio/consumer.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/of_gpio.h> | ||
28 | #include <linux/of_platform.h> | 27 | #include <linux/of_platform.h> |
29 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
30 | #include <linux/regulator/consumer.h> | 29 | #include <linux/regulator/consumer.h> |
@@ -44,9 +43,6 @@ struct panel_desc { | |||
44 | } size; | 43 | } size; |
45 | }; | 44 | }; |
46 | 45 | ||
47 | /* TODO: convert to gpiod_*() API once it's been merged */ | ||
48 | #define GPIO_ACTIVE_LOW (1 << 0) | ||
49 | |||
50 | struct panel_simple { | 46 | struct panel_simple { |
51 | struct drm_panel base; | 47 | struct drm_panel base; |
52 | bool enabled; | 48 | bool enabled; |
@@ -57,8 +53,7 @@ struct panel_simple { | |||
57 | struct regulator *supply; | 53 | struct regulator *supply; |
58 | struct i2c_adapter *ddc; | 54 | struct i2c_adapter *ddc; |
59 | 55 | ||
60 | unsigned long enable_gpio_flags; | 56 | struct gpio_desc *enable_gpio; |
61 | int enable_gpio; | ||
62 | }; | 57 | }; |
63 | 58 | ||
64 | static inline struct panel_simple *to_panel_simple(struct drm_panel *panel) | 59 | static inline struct panel_simple *to_panel_simple(struct drm_panel *panel) |
@@ -110,12 +105,8 @@ static int panel_simple_disable(struct drm_panel *panel) | |||
110 | backlight_update_status(p->backlight); | 105 | backlight_update_status(p->backlight); |
111 | } | 106 | } |
112 | 107 | ||
113 | if (gpio_is_valid(p->enable_gpio)) { | 108 | if (p->enable_gpio) |
114 | if (p->enable_gpio_flags & GPIO_ACTIVE_LOW) | 109 | gpiod_set_value_cansleep(p->enable_gpio, 0); |
115 | gpio_set_value(p->enable_gpio, 1); | ||
116 | else | ||
117 | gpio_set_value(p->enable_gpio, 0); | ||
118 | } | ||
119 | 110 | ||
120 | regulator_disable(p->supply); | 111 | regulator_disable(p->supply); |
121 | p->enabled = false; | 112 | p->enabled = false; |
@@ -137,12 +128,8 @@ static int panel_simple_enable(struct drm_panel *panel) | |||
137 | return err; | 128 | return err; |
138 | } | 129 | } |
139 | 130 | ||
140 | if (gpio_is_valid(p->enable_gpio)) { | 131 | if (p->enable_gpio) |
141 | if (p->enable_gpio_flags & GPIO_ACTIVE_LOW) | 132 | gpiod_set_value_cansleep(p->enable_gpio, 1); |
142 | gpio_set_value(p->enable_gpio, 0); | ||
143 | else | ||
144 | gpio_set_value(p->enable_gpio, 1); | ||
145 | } | ||
146 | 133 | ||
147 | if (p->backlight) { | 134 | if (p->backlight) { |
148 | p->backlight->props.power = FB_BLANK_UNBLANK; | 135 | p->backlight->props.power = FB_BLANK_UNBLANK; |
@@ -185,7 +172,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) | |||
185 | { | 172 | { |
186 | struct device_node *backlight, *ddc; | 173 | struct device_node *backlight, *ddc; |
187 | struct panel_simple *panel; | 174 | struct panel_simple *panel; |
188 | enum of_gpio_flags flags; | ||
189 | int err; | 175 | int err; |
190 | 176 | ||
191 | panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); | 177 | panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); |
@@ -199,29 +185,20 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) | |||
199 | if (IS_ERR(panel->supply)) | 185 | if (IS_ERR(panel->supply)) |
200 | return PTR_ERR(panel->supply); | 186 | return PTR_ERR(panel->supply); |
201 | 187 | ||
202 | panel->enable_gpio = of_get_named_gpio_flags(dev->of_node, | 188 | panel->enable_gpio = devm_gpiod_get(dev, "enable"); |
203 | "enable-gpios", 0, | 189 | if (IS_ERR(panel->enable_gpio)) { |
204 | &flags); | 190 | err = PTR_ERR(panel->enable_gpio); |
205 | if (gpio_is_valid(panel->enable_gpio)) { | 191 | if (err != -ENOENT) { |
206 | unsigned int value; | 192 | dev_err(dev, "failed to request GPIO: %d\n", err); |
207 | |||
208 | if (flags & OF_GPIO_ACTIVE_LOW) | ||
209 | panel->enable_gpio_flags |= GPIO_ACTIVE_LOW; | ||
210 | |||
211 | err = gpio_request(panel->enable_gpio, "enable"); | ||
212 | if (err < 0) { | ||
213 | dev_err(dev, "failed to request GPIO#%u: %d\n", | ||
214 | panel->enable_gpio, err); | ||
215 | return err; | 193 | return err; |
216 | } | 194 | } |
217 | 195 | ||
218 | value = (panel->enable_gpio_flags & GPIO_ACTIVE_LOW) != 0; | 196 | panel->enable_gpio = NULL; |
219 | 197 | } else { | |
220 | err = gpio_direction_output(panel->enable_gpio, value); | 198 | err = gpiod_direction_output(panel->enable_gpio, 0); |
221 | if (err < 0) { | 199 | if (err < 0) { |
222 | dev_err(dev, "failed to setup GPIO%u: %d\n", | 200 | dev_err(dev, "failed to setup GPIO: %d\n", err); |
223 | panel->enable_gpio, err); | 201 | return err; |
224 | goto free_gpio; | ||
225 | } | 202 | } |
226 | } | 203 | } |
227 | 204 | ||
@@ -230,10 +207,8 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) | |||
230 | panel->backlight = of_find_backlight_by_node(backlight); | 207 | panel->backlight = of_find_backlight_by_node(backlight); |
231 | of_node_put(backlight); | 208 | of_node_put(backlight); |
232 | 209 | ||
233 | if (!panel->backlight) { | 210 | if (!panel->backlight) |
234 | err = -EPROBE_DEFER; | 211 | return -EPROBE_DEFER; |
235 | goto free_gpio; | ||
236 | } | ||
237 | } | 212 | } |
238 | 213 | ||
239 | ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0); | 214 | ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0); |
@@ -265,9 +240,6 @@ free_ddc: | |||
265 | free_backlight: | 240 | free_backlight: |
266 | if (panel->backlight) | 241 | if (panel->backlight) |
267 | put_device(&panel->backlight->dev); | 242 | put_device(&panel->backlight->dev); |
268 | free_gpio: | ||
269 | if (gpio_is_valid(panel->enable_gpio)) | ||
270 | gpio_free(panel->enable_gpio); | ||
271 | 243 | ||
272 | return err; | 244 | return err; |
273 | } | 245 | } |
@@ -287,11 +259,6 @@ static int panel_simple_remove(struct device *dev) | |||
287 | if (panel->backlight) | 259 | if (panel->backlight) |
288 | put_device(&panel->backlight->dev); | 260 | put_device(&panel->backlight->dev); |
289 | 261 | ||
290 | if (gpio_is_valid(panel->enable_gpio)) | ||
291 | gpio_free(panel->enable_gpio); | ||
292 | |||
293 | regulator_disable(panel->supply); | ||
294 | |||
295 | return 0; | 262 | return 0; |
296 | } | 263 | } |
297 | 264 | ||
@@ -361,6 +328,28 @@ static const struct panel_desc chunghwa_claa101wb01 = { | |||
361 | }, | 328 | }, |
362 | }; | 329 | }; |
363 | 330 | ||
331 | static const struct drm_display_mode lg_lp129qe_mode = { | ||
332 | .clock = 285250, | ||
333 | .hdisplay = 2560, | ||
334 | .hsync_start = 2560 + 48, | ||
335 | .hsync_end = 2560 + 48 + 32, | ||
336 | .htotal = 2560 + 48 + 32 + 80, | ||
337 | .vdisplay = 1700, | ||
338 | .vsync_start = 1700 + 3, | ||
339 | .vsync_end = 1700 + 3 + 10, | ||
340 | .vtotal = 1700 + 3 + 10 + 36, | ||
341 | .vrefresh = 60, | ||
342 | }; | ||
343 | |||
344 | static const struct panel_desc lg_lp129qe = { | ||
345 | .modes = &lg_lp129qe_mode, | ||
346 | .num_modes = 1, | ||
347 | .size = { | ||
348 | .width = 272, | ||
349 | .height = 181, | ||
350 | }, | ||
351 | }; | ||
352 | |||
364 | static const struct drm_display_mode samsung_ltn101nt05_mode = { | 353 | static const struct drm_display_mode samsung_ltn101nt05_mode = { |
365 | .clock = 54030, | 354 | .clock = 54030, |
366 | .hdisplay = 1024, | 355 | .hdisplay = 1024, |
@@ -394,6 +383,9 @@ static const struct of_device_id platform_of_match[] = { | |||
394 | .compatible = "chunghwa,claa101wb01", | 383 | .compatible = "chunghwa,claa101wb01", |
395 | .data = &chunghwa_claa101wb01 | 384 | .data = &chunghwa_claa101wb01 |
396 | }, { | 385 | }, { |
386 | .compatible = "lg,lp129qe", | ||
387 | .data = &lg_lp129qe, | ||
388 | }, { | ||
397 | .compatible = "samsung,ltn101nt05", | 389 | .compatible = "samsung,ltn101nt05", |
398 | .data = &samsung_ltn101nt05, | 390 | .data = &samsung_ltn101nt05, |
399 | }, { | 391 | }, { |
@@ -433,10 +425,65 @@ static struct platform_driver panel_simple_platform_driver = { | |||
433 | struct panel_desc_dsi { | 425 | struct panel_desc_dsi { |
434 | struct panel_desc desc; | 426 | struct panel_desc desc; |
435 | 427 | ||
428 | unsigned long flags; | ||
436 | enum mipi_dsi_pixel_format format; | 429 | enum mipi_dsi_pixel_format format; |
437 | unsigned int lanes; | 430 | unsigned int lanes; |
438 | }; | 431 | }; |
439 | 432 | ||
433 | static const struct drm_display_mode lg_ld070wx3_sl01_mode = { | ||
434 | .clock = 71000, | ||
435 | .hdisplay = 800, | ||
436 | .hsync_start = 800 + 32, | ||
437 | .hsync_end = 800 + 32 + 1, | ||
438 | .htotal = 800 + 32 + 1 + 57, | ||
439 | .vdisplay = 1280, | ||
440 | .vsync_start = 1280 + 28, | ||
441 | .vsync_end = 1280 + 28 + 1, | ||
442 | .vtotal = 1280 + 28 + 1 + 14, | ||
443 | .vrefresh = 60, | ||
444 | }; | ||
445 | |||
446 | static const struct panel_desc_dsi lg_ld070wx3_sl01 = { | ||
447 | .desc = { | ||
448 | .modes = &lg_ld070wx3_sl01_mode, | ||
449 | .num_modes = 1, | ||
450 | .size = { | ||
451 | .width = 94, | ||
452 | .height = 151, | ||
453 | }, | ||
454 | }, | ||
455 | .flags = MIPI_DSI_MODE_VIDEO, | ||
456 | .format = MIPI_DSI_FMT_RGB888, | ||
457 | .lanes = 4, | ||
458 | }; | ||
459 | |||
460 | static const struct drm_display_mode lg_lh500wx1_sd03_mode = { | ||
461 | .clock = 67000, | ||
462 | .hdisplay = 720, | ||
463 | .hsync_start = 720 + 12, | ||
464 | .hsync_end = 720 + 12 + 4, | ||
465 | .htotal = 720 + 12 + 4 + 112, | ||
466 | .vdisplay = 1280, | ||
467 | .vsync_start = 1280 + 8, | ||
468 | .vsync_end = 1280 + 8 + 4, | ||
469 | .vtotal = 1280 + 8 + 4 + 12, | ||
470 | .vrefresh = 60, | ||
471 | }; | ||
472 | |||
473 | static const struct panel_desc_dsi lg_lh500wx1_sd03 = { | ||
474 | .desc = { | ||
475 | .modes = &lg_lh500wx1_sd03_mode, | ||
476 | .num_modes = 1, | ||
477 | .size = { | ||
478 | .width = 62, | ||
479 | .height = 110, | ||
480 | }, | ||
481 | }, | ||
482 | .flags = MIPI_DSI_MODE_VIDEO, | ||
483 | .format = MIPI_DSI_FMT_RGB888, | ||
484 | .lanes = 4, | ||
485 | }; | ||
486 | |||
440 | static const struct drm_display_mode panasonic_vvx10f004b00_mode = { | 487 | static const struct drm_display_mode panasonic_vvx10f004b00_mode = { |
441 | .clock = 157200, | 488 | .clock = 157200, |
442 | .hdisplay = 1920, | 489 | .hdisplay = 1920, |
@@ -459,12 +506,19 @@ static const struct panel_desc_dsi panasonic_vvx10f004b00 = { | |||
459 | .height = 136, | 506 | .height = 136, |
460 | }, | 507 | }, |
461 | }, | 508 | }, |
509 | .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE, | ||
462 | .format = MIPI_DSI_FMT_RGB888, | 510 | .format = MIPI_DSI_FMT_RGB888, |
463 | .lanes = 4, | 511 | .lanes = 4, |
464 | }; | 512 | }; |
465 | 513 | ||
466 | static const struct of_device_id dsi_of_match[] = { | 514 | static const struct of_device_id dsi_of_match[] = { |
467 | { | 515 | { |
516 | .compatible = "lg,ld070wx3-sl01", | ||
517 | .data = &lg_ld070wx3_sl01 | ||
518 | }, { | ||
519 | .compatible = "lg,lh500wx1-sd03", | ||
520 | .data = &lg_lh500wx1_sd03 | ||
521 | }, { | ||
468 | .compatible = "panasonic,vvx10f004b00", | 522 | .compatible = "panasonic,vvx10f004b00", |
469 | .data = &panasonic_vvx10f004b00 | 523 | .data = &panasonic_vvx10f004b00 |
470 | }, { | 524 | }, { |
@@ -489,6 +543,7 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi) | |||
489 | if (err < 0) | 543 | if (err < 0) |
490 | return err; | 544 | return err; |
491 | 545 | ||
546 | dsi->mode_flags = desc->flags; | ||
492 | dsi->format = desc->format; | 547 | dsi->format = desc->format; |
493 | dsi->lanes = desc->lanes; | 548 | dsi->lanes = desc->lanes; |
494 | 549 | ||