TI AM335x kernel 4.4.12 LCD display 时钟翻转记录
因为公司硬件上已经确定LCD 转LVDS 转换芯片上确认以上升沿时钟为基准,所以只能在软件上调整相关东西。
入口在:
drivers/gpu/drm/tilcdc/tilcdc_drv.c入口函数:
module_init(tilcdc_drm_init);
出口函数:
module_exit(tilcdc_drm_fini); 722 static int __init tilcdc_drm_init(void)
723 {
724 DBG("init");
725 tilcdc_tfp410_init();
726 tilcdc_panel_init(); ---> 这里面有关监视器的初始化----------
727 return platform_driver_register(&tilcdc_platform_driver); |
728 } | | |
drivers/gpu/drm/tilcdc/tilcdc_panel.c ||
452 int __init tilcdc_panel_init(void) <--------------------------
453 {
454 return platform_driver_register(&panel_driver);
455 } |---------- |
437 static struct of_device_id panel_of_match[] = { |
438 { .compatible = "ti,tilcdc,panel", }, |
439 { }, |
440 }; |
441 |
442 struct platform_driver panel_driver = { <------------
443 .probe = panel_probe,
444 .remove = panel_remove,
445 .driver = {
446 .owner = THIS_MODULE,
447 .name = "panel",
448 .of_match_table = panel_of_match,
449 },
450 };
根据panel_of_match[].compatible = "ti,tilcdc,panel", 找到设备树相应内容。
arch/arm/boot/dts/am335x-chenfl.dts47 panel {48 compatible = "ti,tilcdc,panel";49 status = "okay";50 pinctrl-names = "default";51 pinctrl-0 = <&lcd_pins_s0>;52 panel-info {53 ac-bias = <255>;54 ac-bias-intrpt = <0>;55 dma-burst-sz = <16>;56 bpp = <16>;57 fdd = <0x80>;58 sync-edge = <0>;59 sync-ctrl = <1>;60 raster-order = <0>;61 fifo-th = <0>;62 invert-pxl-clk = <1>;63 };64 65 display-timings {66 native-mode = <&timing0>;67 timing0: 800x480 {68 clock-frequency = <33260000>;69 hactive = <800>;70 vactive = <480>;71 hfront-porch = <39>;72 hback-porch = <39>;73 hsync-len = <47>;74 vback-porch = <29>;75 vfront-porch = <13>;76 vsync-len = <2>;77 hsync-active = <1>;78 vsync-active = <1>;79 };80 };81 };
确定平台设备与平台驱动已经相互匹配之后,我们可以直接跟踪驱动的probe
回到drivers/gpu/drm/tilcdc/tilcdc_panel.c
看到:442 struct platform_driver panel_driver = {
443 .probe = panel_probe,
444 .remove = panel_remove,
445 .driver = {
446 .owner = THIS_MODULE,
447 .name = "panel",
448 .of_match_table = panel_of_match,
449 },
450 }; panel_probe:
341 static int panel_probe(struct platform_device *pdev)
342 {
343 struct device_node *bl_node, *node = pdev->dev.of_node;
344 struct panel_module *panel_mod;
345 struct tilcdc_module *mod;
346 struct pinctrl *pinctrl;
347 int ret;
348 /* 如果没有设备树数据就直接跳出来 */
349 /* bail out early if no DT data: */
350 if (!node) {
351 dev_err(&pdev->dev, "device-tree data is missing\n");
352 return -ENXIO;
353 }
354
355 panel_mod = devm_kzalloc(&pdev->dev, sizeof(*panel_mod), GFP_KERNEL);
356 if (!panel_mod)
357 return -ENOMEM;
358
359 bl_node = of_parse_phandle(node, "backlight", 0);
360 if (bl_node) {
361 panel_mod->backlight = of_find_backlight_by_node(bl_node);
362 of_node_put(bl_node);
363
364 if (!panel_mod->backlight)
365 return -EPROBE_DEFER;
366
367 dev_info(&pdev->dev, "found backlight\n");
368 }
369
370 panel_mod->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
371 GPIOD_OUT_LOW);
372 if (IS_ERR(panel_mod->enable_gpio)) {
373 ret = PTR_ERR(panel_mod->enable_gpio);
374 dev_err(&pdev->dev, "failed to request enable GPIO\n");
375 goto fail_backlight;
376 }
377
378 if (panel_mod->enable_gpio)
379 dev_info(&pdev->dev, "found enable GPIO\n");
380
381 mod = &panel_mod->base;
382 pdev->dev.platform_data = mod;
383
384 tilcdc_module_init(mod, "panel", &panel_module_ops);
385
386 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
387 if (IS_ERR(pinctrl))
388 dev_warn(&pdev->dev, "pins are not configured\n");
389 /* 对应时序的设置,和设备树中的display-timings 有关 */
390 panel_mod->timings = of_get_display_timings(node);
391 if (!panel_mod->timings) {
392 dev_err(&pdev->dev, "could not get panel timings\n");
393 ret = -EINVAL;
394 goto fail_free;
395 }
396 /* 对应的相关信息设置,跟panel-info 这个节点有关 */
397 panel_mod->info = of_get_panel_info(node);
398 if (!panel_mod->info) {
399 dev_err(&pdev->dev, "could not get panel info\n");
400 ret = -EINVAL;
401 goto fail_timings;
402 }
403
404 mod->preferred_bpp = panel_mod->info->bpp;
405
406 return 0;
407
408 fail_timings:
409 display_timings_release(panel_mod->timings);
410
411 fail_free:
412 tilcdc_module_cleanup(mod);
413
414 fail_backlight:
415 if (panel_mod->backlight)
416 put_device(&panel_mod->backlight->dev);
417 return ret;
418 } /* 这是上面的 of_get_panel_info 传进来的 */
292 static struct tilcdc_panel_info *of_get_panel_info(struct device_node *np)
293 {
294 struct device_node *info_np;
295 struct tilcdc_panel_info *info;
296 int ret = 0;
297
298 if (!np) {
299 pr_err("%s: no devicenode given\n", __func__);
300 return NULL;
301 }
302
303 info_np = of_get_child_by_name(np, "panel-info");
304 if (!info_np) {
305 pr_err("%s: could not find panel-info node\n", __func__);
306 return NULL;
307 }
308
309 info = kzalloc(sizeof(*info), GFP_KERNEL);
310 if (!info) {
311 pr_err("%s: allocation failed\n", __func__);
312 of_node_put(info_np);
313 return NULL;
314 }
315 /* 这里我们可以看到,如果一个出错,ret 就会为真,这是上面的设备树的必需选项的配对 */
316 ret |= of_property_read_u32(info_np, "ac-bias", &info->ac_bias);
317 ret |= of_property_read_u32(info_np, "ac-bias-intrpt", &info->ac_bias_intrpt);
318 ret |= of_property_read_u32(info_np, "dma-burst-sz", &info->dma_burst_sz);
319 ret |= of_property_read_u32(info_np, "bpp", &info->bpp);
320 ret |= of_property_read_u32(info_np, "fdd", &info->fdd);
321 ret |= of_property_read_u32(info_np, "sync-edge", &info->sync_edge);
322 ret |= of_property_read_u32(info_np, "sync-ctrl", &info->sync_ctrl);
323 ret |= of_property_read_u32(info_np, "raster-order", &info->raster_order);
324 ret |= of_property_read_u32(info_np, "fifo-th", &info->fifo_th);
325
326 /* optional: */ /* 这是可选选项,下面第二个则是时钟反转的选项。在设备中添加一个选项即可。 */
327 info->tft_alt_mode = of_property_read_bool(info_np, "tft-alt-mode");
328 info->invert_pxl_clk = of_property_read_bool(info_np, "invert-pxl-clk");
329
330 if (ret) {
331 pr_err("%s: error reading panel-info properties\n", __func__);
332 kfree(info);
333 of_node_put(info_np);
334 return NULL;
335 }
336 of_node_put(info_np);
337
338 return info;
339 } /* 设备树修改 */47 panel { 48 compatible = "ti,tilcdc,panel"; 49 status = "okay"; 50 pinctrl-names = "default"; 51 pinctrl-0 = <&lcd_pins_s0>; 52 panel-info { 53 ac-bias = <255>; 54 ac-bias-intrpt = <0>; 55 dma-burst-sz = <16>; 56 bpp = <16>; 57 fdd = <0x80>; 58 sync-edge = <0>; 59 sync-ctrl = <1>; 60 raster-order = <0>; 61 fifo-th = <0>; 62 invert-pxl-clk = <1>; /* 添加这个选项设置为1 */ 63 };重新编译设备树,重新启动,看效果。