1 /* 2 * OMAP2plus display device setup / initialization. 3 * 4 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 5 * Senthilvadivu Guruswamy 6 * Sumit Semwal 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 13 * kind, whether express or implied; without even the implied warranty 14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 */ 17 18 #include <linux/kernel.h> 19 #include <linux/init.h> 20 #include <linux/platform_device.h> 21 #include <linux/io.h> 22 #include <linux/clk.h> 23 #include <linux/err.h> 24 25 #include <video/omapdss.h> 26 #include <plat/omap_hwmod.h> 27 #include <plat/omap_device.h> 28 29 static struct platform_device omap_display_device = { 30 .name = "omapdss", 31 .id = -1, 32 .dev = { 33 .platform_data = NULL, 34 }, 35 }; 36 37 static struct omap_device_pm_latency omap_dss_latency[] = { 38 [0] = { 39 .deactivate_func = omap_device_idle_hwmods, 40 .activate_func = omap_device_enable_hwmods, 41 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, 42 }, 43 }; 44 45 /* oh_core is used for getting opt-clocks */ 46 static struct omap_hwmod *oh_core; 47 48 static bool opt_clock_available(const char *clk_role) 49 { 50 int i; 51 52 for (i = 0; i < oh_core->opt_clks_cnt; i++) { 53 if (!strcmp(oh_core->opt_clks[i].role, clk_role)) 54 return true; 55 } 56 return false; 57 } 58 59 struct omap_dss_hwmod_data { 60 const char *oh_name; 61 const char *dev_name; 62 const int id; 63 }; 64 65 static const struct omap_dss_hwmod_data omap2_dss_hwmod_data[] __initdata = { 66 { "dss_core", "omapdss_dss", -1 }, 67 { "dss_dispc", "omapdss_dispc", -1 }, 68 { "dss_rfbi", "omapdss_rfbi", -1 }, 69 { "dss_venc", "omapdss_venc", -1 }, 70 }; 71 72 static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = { 73 { "dss_core", "omapdss_dss", -1 }, 74 { "dss_dispc", "omapdss_dispc", -1 }, 75 { "dss_rfbi", "omapdss_rfbi", -1 }, 76 { "dss_venc", "omapdss_venc", -1 }, 77 { "dss_dsi1", "omapdss_dsi1", -1 }, 78 }; 79 80 static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = { 81 { "dss_core", "omapdss_dss", -1 }, 82 { "dss_dispc", "omapdss_dispc", -1 }, 83 { "dss_rfbi", "omapdss_rfbi", -1 }, 84 { "dss_venc", "omapdss_venc", -1 }, 85 { "dss_dsi1", "omapdss_dsi1", -1 }, 86 { "dss_dsi2", "omapdss_dsi2", -1 }, 87 { "dss_hdmi", "omapdss_hdmi", -1 }, 88 }; 89 90 int __init omap_display_init(struct omap_dss_board_info *board_data) 91 { 92 int r = 0; 93 struct omap_hwmod *oh; 94 struct omap_device *od; 95 int i, oh_count; 96 struct omap_display_platform_data pdata; 97 const struct omap_dss_hwmod_data *curr_dss_hwmod; 98 99 memset(&pdata, 0, sizeof(pdata)); 100 101 if (cpu_is_omap24xx()) { 102 curr_dss_hwmod = omap2_dss_hwmod_data; 103 oh_count = ARRAY_SIZE(omap2_dss_hwmod_data); 104 } else if (cpu_is_omap34xx()) { 105 curr_dss_hwmod = omap3_dss_hwmod_data; 106 oh_count = ARRAY_SIZE(omap3_dss_hwmod_data); 107 } else { 108 curr_dss_hwmod = omap4_dss_hwmod_data; 109 oh_count = ARRAY_SIZE(omap4_dss_hwmod_data); 110 } 111 112 /* opt_clks are always associated with dss hwmod */ 113 oh_core = omap_hwmod_lookup("dss_core"); 114 if (!oh_core) { 115 pr_err("Could not look up dss_core.\n"); 116 return -ENODEV; 117 } 118 119 pdata.board_data = board_data; 120 pdata.board_data->get_last_off_on_transaction_id = NULL; 121 pdata.opt_clock_available = opt_clock_available; 122 123 for (i = 0; i < oh_count; i++) { 124 oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name); 125 if (!oh) { 126 pr_err("Could not look up %s\n", 127 curr_dss_hwmod[i].oh_name); 128 return -ENODEV; 129 } 130 131 od = omap_device_build(curr_dss_hwmod[i].dev_name, 132 curr_dss_hwmod[i].id, oh, &pdata, 133 sizeof(struct omap_display_platform_data), 134 omap_dss_latency, 135 ARRAY_SIZE(omap_dss_latency), 0); 136 137 if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n", 138 curr_dss_hwmod[i].oh_name)) 139 return -ENODEV; 140 } 141 omap_display_device.dev.platform_data = board_data; 142 143 r = platform_device_register(&omap_display_device); 144 if (r < 0) 145 printk(KERN_ERR "Unable to register OMAP-Display device\n"); 146 147 return r; 148 } 149