aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tilcdc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-14 03:39:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-14 03:39:08 -0400
commit2d65a9f48fcdf7866aab6457bc707ca233e0c791 (patch)
treef93e5838d6ac2e59434367f4ff905f7d9c45fc2b /drivers/gpu/drm/tilcdc
parentda92da3638a04894afdca8b99e973ddd20268471 (diff)
parentdfda0df3426483cf5fc7441f23f318edbabecb03 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "This is the main git pull for the drm, I pretty much froze major pulls at -rc5/6 time, and haven't had much fallout, so will probably continue doing that. Lots of changes all over, big internal header cleanup to make it clear drm features are legacy things and what are things that modern KMS drivers should be using. Also big move to use the new generic fences in all the TTM drivers. core: atomic prep work, vblank rework changes, allows immediate vblank disables major header reworking and cleanups to better delinate legacy interfaces from what KMS drivers should be using. cursor planes locking fixes ttm: move to generic fences (affects all TTM drivers) ppc64 caching fixes radeon: userptr support, uvd for old asics, reset rework for fence changes better buffer placement changes, dpm feature enablement hdmi audio support fixes intel: Cherryview work, 180 degree rotation, skylake prep work, execlist command submission full ppgtt prep work cursor improvements edid caching, vdd handling improvements nouveau: fence reworking kepler memory clock work gt21x clock work fan control improvements hdmi infoframe fixes DP audio ast: ppc64 fixes caching fix rcar: rcar-du DT support ipuv3: prep work for capture support msm: LVDS support for mdp4, new panel, gpu refactoring exynos: exynos3250 SoC support, drop bad mmap interface, mipi dsi changes, and component match support" * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (640 commits) drm/mst: rework payload table allocation to conform better. drm/ast: Fix HW cursor image drm/radeon/kv: add uvd/vce info to dpm debugfs output drm/radeon/ci: add uvd/vce info to dpm debugfs output drm/radeon: export reservation_object from dmabuf to ttm drm/radeon: cope with foreign fences inside the reservation object drm/radeon: cope with foreign fences inside display drm/core: use helper to check driver features drm/radeon/cik: write gfx ucode version to ucode addr reg drm/radeon/si: print full CS when we hit a packet 0 drm/radeon: remove unecessary includes drm/radeon/combios: declare legacy_connector_convert as static drm/radeon/atombios: declare connector convert tables as static drm/radeon: drop btc_get_max_clock_from_voltage_dependency_table drm/radeon/dpm: drop clk/voltage dependency filters for BTC drm/radeon/dpm: drop clk/voltage dependency filters for CI drm/radeon/dpm: drop clk/voltage dependency filters for SI drm/radeon/dpm: drop clk/voltage dependency filters for NI drm/radeon: disable audio when we disable hdmi (v2) drm/radeon: split audio enable between eg and r600 (v2) ...
Diffstat (limited to 'drivers/gpu/drm/tilcdc')
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c61
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_panel.c74
2 files changed, 108 insertions, 27 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 6be623b4a86f..79a34cbd29f5 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -84,6 +84,7 @@ static int modeset_init(struct drm_device *dev)
84 if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) { 84 if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) {
85 /* oh nos! */ 85 /* oh nos! */
86 dev_err(dev->dev, "no encoders/connectors found\n"); 86 dev_err(dev->dev, "no encoders/connectors found\n");
87 drm_mode_config_cleanup(dev);
87 return -ENXIO; 88 return -ENXIO;
88 } 89 }
89 90
@@ -172,33 +173,37 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
172 dev->dev_private = priv; 173 dev->dev_private = priv;
173 174
174 priv->wq = alloc_ordered_workqueue("tilcdc", 0); 175 priv->wq = alloc_ordered_workqueue("tilcdc", 0);
176 if (!priv->wq) {
177 ret = -ENOMEM;
178 goto fail_free_priv;
179 }
175 180
176 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 181 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
177 if (!res) { 182 if (!res) {
178 dev_err(dev->dev, "failed to get memory resource\n"); 183 dev_err(dev->dev, "failed to get memory resource\n");
179 ret = -EINVAL; 184 ret = -EINVAL;
180 goto fail; 185 goto fail_free_wq;
181 } 186 }
182 187
183 priv->mmio = ioremap_nocache(res->start, resource_size(res)); 188 priv->mmio = ioremap_nocache(res->start, resource_size(res));
184 if (!priv->mmio) { 189 if (!priv->mmio) {
185 dev_err(dev->dev, "failed to ioremap\n"); 190 dev_err(dev->dev, "failed to ioremap\n");
186 ret = -ENOMEM; 191 ret = -ENOMEM;
187 goto fail; 192 goto fail_free_wq;
188 } 193 }
189 194
190 priv->clk = clk_get(dev->dev, "fck"); 195 priv->clk = clk_get(dev->dev, "fck");
191 if (IS_ERR(priv->clk)) { 196 if (IS_ERR(priv->clk)) {
192 dev_err(dev->dev, "failed to get functional clock\n"); 197 dev_err(dev->dev, "failed to get functional clock\n");
193 ret = -ENODEV; 198 ret = -ENODEV;
194 goto fail; 199 goto fail_iounmap;
195 } 200 }
196 201
197 priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck"); 202 priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck");
198 if (IS_ERR(priv->clk)) { 203 if (IS_ERR(priv->clk)) {
199 dev_err(dev->dev, "failed to get display clock\n"); 204 dev_err(dev->dev, "failed to get display clock\n");
200 ret = -ENODEV; 205 ret = -ENODEV;
201 goto fail; 206 goto fail_put_clk;
202 } 207 }
203 208
204#ifdef CONFIG_CPU_FREQ 209#ifdef CONFIG_CPU_FREQ
@@ -208,7 +213,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
208 CPUFREQ_TRANSITION_NOTIFIER); 213 CPUFREQ_TRANSITION_NOTIFIER);
209 if (ret) { 214 if (ret) {
210 dev_err(dev->dev, "failed to register cpufreq notifier\n"); 215 dev_err(dev->dev, "failed to register cpufreq notifier\n");
211 goto fail; 216 goto fail_put_disp_clk;
212 } 217 }
213#endif 218#endif
214 219
@@ -253,13 +258,13 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
253 ret = modeset_init(dev); 258 ret = modeset_init(dev);
254 if (ret < 0) { 259 if (ret < 0) {
255 dev_err(dev->dev, "failed to initialize mode setting\n"); 260 dev_err(dev->dev, "failed to initialize mode setting\n");
256 goto fail; 261 goto fail_cpufreq_unregister;
257 } 262 }
258 263
259 ret = drm_vblank_init(dev, 1); 264 ret = drm_vblank_init(dev, 1);
260 if (ret < 0) { 265 if (ret < 0) {
261 dev_err(dev->dev, "failed to initialize vblank\n"); 266 dev_err(dev->dev, "failed to initialize vblank\n");
262 goto fail; 267 goto fail_mode_config_cleanup;
263 } 268 }
264 269
265 pm_runtime_get_sync(dev->dev); 270 pm_runtime_get_sync(dev->dev);
@@ -267,7 +272,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
267 pm_runtime_put_sync(dev->dev); 272 pm_runtime_put_sync(dev->dev);
268 if (ret < 0) { 273 if (ret < 0) {
269 dev_err(dev->dev, "failed to install IRQ handler\n"); 274 dev_err(dev->dev, "failed to install IRQ handler\n");
270 goto fail; 275 goto fail_vblank_cleanup;
271 } 276 }
272 277
273 platform_set_drvdata(pdev, dev); 278 platform_set_drvdata(pdev, dev);
@@ -283,13 +288,48 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
283 priv->fbdev = drm_fbdev_cma_init(dev, bpp, 288 priv->fbdev = drm_fbdev_cma_init(dev, bpp,
284 dev->mode_config.num_crtc, 289 dev->mode_config.num_crtc,
285 dev->mode_config.num_connector); 290 dev->mode_config.num_connector);
291 if (IS_ERR(priv->fbdev)) {
292 ret = PTR_ERR(priv->fbdev);
293 goto fail_irq_uninstall;
294 }
286 295
287 drm_kms_helper_poll_init(dev); 296 drm_kms_helper_poll_init(dev);
288 297
289 return 0; 298 return 0;
290 299
291fail: 300fail_irq_uninstall:
292 tilcdc_unload(dev); 301 pm_runtime_get_sync(dev->dev);
302 drm_irq_uninstall(dev);
303 pm_runtime_put_sync(dev->dev);
304
305fail_vblank_cleanup:
306 drm_vblank_cleanup(dev);
307
308fail_mode_config_cleanup:
309 drm_mode_config_cleanup(dev);
310
311fail_cpufreq_unregister:
312 pm_runtime_disable(dev->dev);
313#ifdef CONFIG_CPU_FREQ
314 cpufreq_unregister_notifier(&priv->freq_transition,
315 CPUFREQ_TRANSITION_NOTIFIER);
316fail_put_disp_clk:
317 clk_put(priv->disp_clk);
318#endif
319
320fail_put_clk:
321 clk_put(priv->clk);
322
323fail_iounmap:
324 iounmap(priv->mmio);
325
326fail_free_wq:
327 flush_workqueue(priv->wq);
328 destroy_workqueue(priv->wq);
329
330fail_free_priv:
331 dev->dev_private = NULL;
332 kfree(priv);
293 return ret; 333 return ret;
294} 334}
295 335
@@ -502,6 +542,7 @@ static struct drm_driver tilcdc_driver = {
502 .unload = tilcdc_unload, 542 .unload = tilcdc_unload,
503 .preclose = tilcdc_preclose, 543 .preclose = tilcdc_preclose,
504 .lastclose = tilcdc_lastclose, 544 .lastclose = tilcdc_lastclose,
545 .set_busid = drm_platform_set_busid,
505 .irq_handler = tilcdc_irq, 546 .irq_handler = tilcdc_irq,
506 .irq_preinstall = tilcdc_irq_preinstall, 547 .irq_preinstall = tilcdc_irq_preinstall,
507 .irq_postinstall = tilcdc_irq_postinstall, 548 .irq_postinstall = tilcdc_irq_postinstall,
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
index 4c7aa1d8134f..7a0315855e90 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
@@ -18,6 +18,7 @@
18#include <linux/pinctrl/pinmux.h> 18#include <linux/pinctrl/pinmux.h>
19#include <linux/pinctrl/consumer.h> 19#include <linux/pinctrl/consumer.h>
20#include <linux/backlight.h> 20#include <linux/backlight.h>
21#include <linux/gpio/consumer.h>
21#include <video/display_timing.h> 22#include <video/display_timing.h>
22#include <video/of_display_timing.h> 23#include <video/of_display_timing.h>
23#include <video/videomode.h> 24#include <video/videomode.h>
@@ -29,6 +30,7 @@ struct panel_module {
29 struct tilcdc_panel_info *info; 30 struct tilcdc_panel_info *info;
30 struct display_timings *timings; 31 struct display_timings *timings;
31 struct backlight_device *backlight; 32 struct backlight_device *backlight;
33 struct gpio_desc *enable_gpio;
32}; 34};
33#define to_panel_module(x) container_of(x, struct panel_module, base) 35#define to_panel_module(x) container_of(x, struct panel_module, base)
34 36
@@ -55,13 +57,17 @@ static void panel_encoder_dpms(struct drm_encoder *encoder, int mode)
55{ 57{
56 struct panel_encoder *panel_encoder = to_panel_encoder(encoder); 58 struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
57 struct backlight_device *backlight = panel_encoder->mod->backlight; 59 struct backlight_device *backlight = panel_encoder->mod->backlight;
60 struct gpio_desc *gpio = panel_encoder->mod->enable_gpio;
58 61
59 if (!backlight) 62 if (backlight) {
60 return; 63 backlight->props.power = mode == DRM_MODE_DPMS_ON ?
64 FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
65 backlight_update_status(backlight);
66 }
61 67
62 backlight->props.power = mode == DRM_MODE_DPMS_ON 68 if (gpio)
63 ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 69 gpiod_set_value_cansleep(gpio,
64 backlight_update_status(backlight); 70 mode == DRM_MODE_DPMS_ON ? 1 : 0);
65} 71}
66 72
67static bool panel_encoder_mode_fixup(struct drm_encoder *encoder, 73static bool panel_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -311,6 +317,7 @@ static struct tilcdc_panel_info *of_get_panel_info(struct device_node *np)
311 info = kzalloc(sizeof(*info), GFP_KERNEL); 317 info = kzalloc(sizeof(*info), GFP_KERNEL);
312 if (!info) { 318 if (!info) {
313 pr_err("%s: allocation failed\n", __func__); 319 pr_err("%s: allocation failed\n", __func__);
320 of_node_put(info_np);
314 return NULL; 321 return NULL;
315 } 322 }
316 323
@@ -331,22 +338,21 @@ static struct tilcdc_panel_info *of_get_panel_info(struct device_node *np)
331 if (ret) { 338 if (ret) {
332 pr_err("%s: error reading panel-info properties\n", __func__); 339 pr_err("%s: error reading panel-info properties\n", __func__);
333 kfree(info); 340 kfree(info);
341 of_node_put(info_np);
334 return NULL; 342 return NULL;
335 } 343 }
344 of_node_put(info_np);
336 345
337 return info; 346 return info;
338} 347}
339 348
340static struct of_device_id panel_of_match[];
341
342static int panel_probe(struct platform_device *pdev) 349static int panel_probe(struct platform_device *pdev)
343{ 350{
344 struct device_node *node = pdev->dev.of_node; 351 struct device_node *bl_node, *node = pdev->dev.of_node;
345 struct panel_module *panel_mod; 352 struct panel_module *panel_mod;
346 struct tilcdc_module *mod; 353 struct tilcdc_module *mod;
347 struct pinctrl *pinctrl; 354 struct pinctrl *pinctrl;
348 int ret = -EINVAL; 355 int ret;
349
350 356
351 /* bail out early if no DT data: */ 357 /* bail out early if no DT data: */
352 if (!node) { 358 if (!node) {
@@ -354,10 +360,40 @@ static int panel_probe(struct platform_device *pdev)
354 return -ENXIO; 360 return -ENXIO;
355 } 361 }
356 362
357 panel_mod = kzalloc(sizeof(*panel_mod), GFP_KERNEL); 363 panel_mod = devm_kzalloc(&pdev->dev, sizeof(*panel_mod), GFP_KERNEL);
358 if (!panel_mod) 364 if (!panel_mod)
359 return -ENOMEM; 365 return -ENOMEM;
360 366
367 bl_node = of_parse_phandle(node, "backlight", 0);
368 if (bl_node) {
369 panel_mod->backlight = of_find_backlight_by_node(bl_node);
370 of_node_put(bl_node);
371
372 if (!panel_mod->backlight)
373 return -EPROBE_DEFER;
374
375 dev_info(&pdev->dev, "found backlight\n");
376 }
377
378 panel_mod->enable_gpio = devm_gpiod_get(&pdev->dev, "enable");
379 if (IS_ERR(panel_mod->enable_gpio)) {
380 ret = PTR_ERR(panel_mod->enable_gpio);
381 if (ret != -ENOENT) {
382 dev_err(&pdev->dev, "failed to request enable GPIO\n");
383 goto fail_backlight;
384 }
385
386 /* Optional GPIO is not here, continue silently. */
387 panel_mod->enable_gpio = NULL;
388 } else {
389 ret = gpiod_direction_output(panel_mod->enable_gpio, 0);
390 if (ret < 0) {
391 dev_err(&pdev->dev, "failed to setup GPIO\n");
392 goto fail_backlight;
393 }
394 dev_info(&pdev->dev, "found enable GPIO\n");
395 }
396
361 mod = &panel_mod->base; 397 mod = &panel_mod->base;
362 pdev->dev.platform_data = mod; 398 pdev->dev.platform_data = mod;
363 399
@@ -370,29 +406,30 @@ static int panel_probe(struct platform_device *pdev)
370 panel_mod->timings = of_get_display_timings(node); 406 panel_mod->timings = of_get_display_timings(node);
371 if (!panel_mod->timings) { 407 if (!panel_mod->timings) {
372 dev_err(&pdev->dev, "could not get panel timings\n"); 408 dev_err(&pdev->dev, "could not get panel timings\n");
409 ret = -EINVAL;
373 goto fail_free; 410 goto fail_free;
374 } 411 }
375 412
376 panel_mod->info = of_get_panel_info(node); 413 panel_mod->info = of_get_panel_info(node);
377 if (!panel_mod->info) { 414 if (!panel_mod->info) {
378 dev_err(&pdev->dev, "could not get panel info\n"); 415 dev_err(&pdev->dev, "could not get panel info\n");
416 ret = -EINVAL;
379 goto fail_timings; 417 goto fail_timings;
380 } 418 }
381 419
382 mod->preferred_bpp = panel_mod->info->bpp; 420 mod->preferred_bpp = panel_mod->info->bpp;
383 421
384 panel_mod->backlight = of_find_backlight_by_node(node);
385 if (panel_mod->backlight)
386 dev_info(&pdev->dev, "found backlight\n");
387
388 return 0; 422 return 0;
389 423
390fail_timings: 424fail_timings:
391 display_timings_release(panel_mod->timings); 425 display_timings_release(panel_mod->timings);
392 426
393fail_free: 427fail_free:
394 kfree(panel_mod);
395 tilcdc_module_cleanup(mod); 428 tilcdc_module_cleanup(mod);
429
430fail_backlight:
431 if (panel_mod->backlight)
432 put_device(&panel_mod->backlight->dev);
396 return ret; 433 return ret;
397} 434}
398 435
@@ -400,12 +437,15 @@ static int panel_remove(struct platform_device *pdev)
400{ 437{
401 struct tilcdc_module *mod = dev_get_platdata(&pdev->dev); 438 struct tilcdc_module *mod = dev_get_platdata(&pdev->dev);
402 struct panel_module *panel_mod = to_panel_module(mod); 439 struct panel_module *panel_mod = to_panel_module(mod);
440 struct backlight_device *backlight = panel_mod->backlight;
441
442 if (backlight)
443 put_device(&backlight->dev);
403 444
404 display_timings_release(panel_mod->timings); 445 display_timings_release(panel_mod->timings);
405 446
406 tilcdc_module_cleanup(mod); 447 tilcdc_module_cleanup(mod);
407 kfree(panel_mod->info); 448 kfree(panel_mod->info);
408 kfree(panel_mod);
409 449
410 return 0; 450 return 0;
411} 451}