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 | |
| 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')
| -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 | ||
