dss.c 21 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. /*
  2. * linux/drivers/video/omap2/dss/dss.c
  3. *
  4. * Copyright (C) 2009 Nokia Corporation
  5. * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
  6. *
  7. * Some code and ideas taken from drivers/video/omap/ driver
  8. * by Imre Deak.
  9. *
  10. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License version 2 as published by
  12. * the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  17. * more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along with
  20. * this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. #define DSS_SUBSYS_NAME "DSS"
  23. #include <linux/kernel.h>
  24. #include <linux/io.h>
  25. #include <linux/err.h>
  26. #include <linux/delay.h>
  27. #include <linux/seq_file.h>
  28. #include <linux/clk.h>
  29. #include <plat/display.h>
  30. #include <plat/clock.h>
  31. #include "dss.h"
  32. #include "dss_features.h"
  33. #define DSS_SZ_REGS SZ_512
  34. struct dss_reg {
  35. u16 idx;
  36. };
  37. #define DSS_REG(idx) ((const struct dss_reg) { idx })
  38. #define DSS_REVISION DSS_REG(0x0000)
  39. #define DSS_SYSCONFIG DSS_REG(0x0010)
  40. #define DSS_SYSSTATUS DSS_REG(0x0014)
  41. #define DSS_IRQSTATUS DSS_REG(0x0018)
  42. #define DSS_CONTROL DSS_REG(0x0040)
  43. #define DSS_SDI_CONTROL DSS_REG(0x0044)
  44. #define DSS_PLL_CONTROL DSS_REG(0x0048)
  45. #define DSS_SDI_STATUS DSS_REG(0x005C)
  46. #define REG_GET(idx, start, end) \
  47. FLD_GET(dss_read_reg(idx), start, end)
  48. #define REG_FLD_MOD(idx, val, start, end) \
  49. dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
  50. static struct {
  51. struct platform_device *pdev;
  52. void __iomem *base;
  53. int ctx_id;
  54. struct clk *dpll4_m4_ck;
  55. struct clk *dss_ick;
  56. struct clk *dss_fck;
  57. struct clk *dss_sys_clk;
  58. struct clk *dss_tv_fck;
  59. struct clk *dss_video_fck;
  60. unsigned num_clks_enabled;
  61. unsigned long cache_req_pck;
  62. unsigned long cache_prate;
  63. struct dss_clock_info cache_dss_cinfo;
  64. struct dispc_clock_info cache_dispc_cinfo;
  65. enum dss_clk_source dsi_clk_source;
  66. enum dss_clk_source dispc_clk_source;
  67. u32 ctx[DSS_SZ_REGS / sizeof(u32)];
  68. } dss;
  69. static void dss_clk_enable_all_no_ctx(void);
  70. static void dss_clk_disable_all_no_ctx(void);
  71. static void dss_clk_enable_no_ctx(enum dss_clock clks);
  72. static void dss_clk_disable_no_ctx(enum dss_clock clks);
  73. static int _omap_dss_wait_reset(void);
  74. static inline void dss_write_reg(const struct dss_reg idx, u32 val)
  75. {
  76. __raw_writel(val, dss.base + idx.idx);
  77. }
  78. static inline u32 dss_read_reg(const struct dss_reg idx)
  79. {
  80. return __raw_readl(dss.base + idx.idx);
  81. }
  82. #define SR(reg) \
  83. dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
  84. #define RR(reg) \
  85. dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
  86. void dss_save_context(void)
  87. {
  88. if (cpu_is_omap24xx())
  89. return;
  90. SR(SYSCONFIG);
  91. SR(CONTROL);
  92. if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
  93. OMAP_DISPLAY_TYPE_SDI) {
  94. SR(SDI_CONTROL);
  95. SR(PLL_CONTROL);
  96. }
  97. }
  98. void dss_restore_context(void)
  99. {
  100. if (_omap_dss_wait_reset())
  101. DSSERR("DSS not coming out of reset after sleep\n");
  102. RR(SYSCONFIG);
  103. RR(CONTROL);
  104. if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
  105. OMAP_DISPLAY_TYPE_SDI) {
  106. RR(SDI_CONTROL);
  107. RR(PLL_CONTROL);
  108. }
  109. }
  110. #undef SR
  111. #undef RR
  112. void dss_sdi_init(u8 datapairs)
  113. {
  114. u32 l;
  115. BUG_ON(datapairs > 3 || datapairs < 1);
  116. l = dss_read_reg(DSS_SDI_CONTROL);
  117. l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
  118. l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
  119. l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
  120. dss_write_reg(DSS_SDI_CONTROL, l);
  121. l = dss_read_reg(DSS_PLL_CONTROL);
  122. l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
  123. l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
  124. l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
  125. dss_write_reg(DSS_PLL_CONTROL, l);
  126. }
  127. int dss_sdi_enable(void)
  128. {
  129. unsigned long timeout;
  130. dispc_pck_free_enable(1);
  131. /* Reset SDI PLL */
  132. REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
  133. udelay(1); /* wait 2x PCLK */
  134. /* Lock SDI PLL */
  135. REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
  136. /* Waiting for PLL lock request to complete */
  137. timeout = jiffies + msecs_to_jiffies(500);
  138. while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
  139. if (time_after_eq(jiffies, timeout)) {
  140. DSSERR("PLL lock request timed out\n");
  141. goto err1;
  142. }
  143. }
  144. /* Clearing PLL_GO bit */
  145. REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
  146. /* Waiting for PLL to lock */
  147. timeout = jiffies + msecs_to_jiffies(500);
  148. while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
  149. if (time_after_eq(jiffies, timeout)) {
  150. DSSERR("PLL lock timed out\n");
  151. goto err1;
  152. }
  153. }
  154. dispc_lcd_enable_signal(1);
  155. /* Waiting for SDI reset to complete */
  156. timeout = jiffies + msecs_to_jiffies(500);
  157. while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
  158. if (time_after_eq(jiffies, timeout)) {
  159. DSSERR("SDI reset timed out\n");
  160. goto err2;
  161. }
  162. }
  163. return 0;
  164. err2:
  165. dispc_lcd_enable_signal(0);
  166. err1:
  167. /* Reset SDI PLL */
  168. REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
  169. dispc_pck_free_enable(0);
  170. return -ETIMEDOUT;
  171. }
  172. void dss_sdi_disable(void)
  173. {
  174. dispc_lcd_enable_signal(0);
  175. dispc_pck_free_enable(0);
  176. /* Reset SDI PLL */
  177. REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
  178. }
  179. void dss_dump_clocks(struct seq_file *s)
  180. {
  181. unsigned long dpll4_ck_rate;
  182. unsigned long dpll4_m4_ck_rate;
  183. dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
  184. dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
  185. dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
  186. seq_printf(s, "- DSS -\n");
  187. seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
  188. if (cpu_is_omap3630())
  189. seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n",
  190. dpll4_ck_rate,
  191. dpll4_ck_rate / dpll4_m4_ck_rate,
  192. dss_clk_get_rate(DSS_CLK_FCK));
  193. else
  194. seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n",
  195. dpll4_ck_rate,
  196. dpll4_ck_rate / dpll4_m4_ck_rate,
  197. dss_clk_get_rate(DSS_CLK_FCK));
  198. dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
  199. }
  200. void dss_dump_regs(struct seq_file *s)
  201. {
  202. #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
  203. dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
  204. DUMPREG(DSS_REVISION);
  205. DUMPREG(DSS_SYSCONFIG);
  206. DUMPREG(DSS_SYSSTATUS);
  207. DUMPREG(DSS_IRQSTATUS);
  208. DUMPREG(DSS_CONTROL);
  209. if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
  210. OMAP_DISPLAY_TYPE_SDI) {
  211. DUMPREG(DSS_SDI_CONTROL);
  212. DUMPREG(DSS_PLL_CONTROL);
  213. DUMPREG(DSS_SDI_STATUS);
  214. }
  215. dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
  216. #undef DUMPREG
  217. }
  218. void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
  219. {
  220. int b;
  221. BUG_ON(clk_src != DSS_SRC_DSI1_PLL_FCLK &&
  222. clk_src != DSS_SRC_DSS1_ALWON_FCLK);
  223. b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
  224. if (clk_src == DSS_SRC_DSI1_PLL_FCLK)
  225. dsi_wait_dsi1_pll_active();
  226. REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */
  227. dss.dispc_clk_source = clk_src;
  228. }
  229. void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
  230. {
  231. int b;
  232. BUG_ON(clk_src != DSS_SRC_DSI2_PLL_FCLK &&
  233. clk_src != DSS_SRC_DSS1_ALWON_FCLK);
  234. b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
  235. if (clk_src == DSS_SRC_DSI2_PLL_FCLK)
  236. dsi_wait_dsi2_pll_active();
  237. REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
  238. dss.dsi_clk_source = clk_src;
  239. }
  240. enum dss_clk_source dss_get_dispc_clk_source(void)
  241. {
  242. return dss.dispc_clk_source;
  243. }
  244. enum dss_clk_source dss_get_dsi_clk_source(void)
  245. {
  246. return dss.dsi_clk_source;
  247. }
  248. /* calculate clock rates using dividers in cinfo */
  249. int dss_calc_clock_rates(struct dss_clock_info *cinfo)
  250. {
  251. unsigned long prate;
  252. if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) ||
  253. cinfo->fck_div == 0)
  254. return -EINVAL;
  255. prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
  256. cinfo->fck = prate / cinfo->fck_div;
  257. return 0;
  258. }
  259. int dss_set_clock_div(struct dss_clock_info *cinfo)
  260. {
  261. unsigned long prate;
  262. int r;
  263. if (cpu_is_omap34xx()) {
  264. prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
  265. DSSDBG("dpll4_m4 = %ld\n", prate);
  266. r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
  267. if (r)
  268. return r;
  269. }
  270. DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
  271. return 0;
  272. }
  273. int dss_get_clock_div(struct dss_clock_info *cinfo)
  274. {
  275. cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
  276. if (cpu_is_omap34xx()) {
  277. unsigned long prate;
  278. prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
  279. if (cpu_is_omap3630())
  280. cinfo->fck_div = prate / (cinfo->fck);
  281. else
  282. cinfo->fck_div = prate / (cinfo->fck / 2);
  283. } else {
  284. cinfo->fck_div = 0;
  285. }
  286. return 0;
  287. }
  288. unsigned long dss_get_dpll4_rate(void)
  289. {
  290. if (cpu_is_omap34xx())
  291. return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
  292. else
  293. return 0;
  294. }
  295. int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
  296. struct dss_clock_info *dss_cinfo,
  297. struct dispc_clock_info *dispc_cinfo)
  298. {
  299. unsigned long prate;
  300. struct dss_clock_info best_dss;
  301. struct dispc_clock_info best_dispc;
  302. unsigned long fck;
  303. u16 fck_div;
  304. int match = 0;
  305. int min_fck_per_pck;
  306. prate = dss_get_dpll4_rate();
  307. fck = dss_clk_get_rate(DSS_CLK_FCK);
  308. if (req_pck == dss.cache_req_pck &&
  309. ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
  310. dss.cache_dss_cinfo.fck == fck)) {
  311. DSSDBG("dispc clock info found from cache.\n");
  312. *dss_cinfo = dss.cache_dss_cinfo;
  313. *dispc_cinfo = dss.cache_dispc_cinfo;
  314. return 0;
  315. }
  316. min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
  317. if (min_fck_per_pck &&
  318. req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
  319. DSSERR("Requested pixel clock not possible with the current "
  320. "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
  321. "the constraint off.\n");
  322. min_fck_per_pck = 0;
  323. }
  324. retry:
  325. memset(&best_dss, 0, sizeof(best_dss));
  326. memset(&best_dispc, 0, sizeof(best_dispc));
  327. if (cpu_is_omap24xx()) {
  328. struct dispc_clock_info cur_dispc;
  329. /* XXX can we change the clock on omap2? */
  330. fck = dss_clk_get_rate(DSS_CLK_FCK);
  331. fck_div = 1;
  332. dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
  333. match = 1;
  334. best_dss.fck = fck;
  335. best_dss.fck_div = fck_div;
  336. best_dispc = cur_dispc;
  337. goto found;
  338. } else if (cpu_is_omap34xx()) {
  339. for (fck_div = (cpu_is_omap3630() ? 32 : 16);
  340. fck_div > 0; --fck_div) {
  341. struct dispc_clock_info cur_dispc;
  342. if (cpu_is_omap3630())
  343. fck = prate / fck_div;
  344. else
  345. fck = prate / fck_div * 2;
  346. if (fck > DISPC_MAX_FCK)
  347. continue;
  348. if (min_fck_per_pck &&
  349. fck < req_pck * min_fck_per_pck)
  350. continue;
  351. match = 1;
  352. dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
  353. if (abs(cur_dispc.pck - req_pck) <
  354. abs(best_dispc.pck - req_pck)) {
  355. best_dss.fck = fck;
  356. best_dss.fck_div = fck_div;
  357. best_dispc = cur_dispc;
  358. if (cur_dispc.pck == req_pck)
  359. goto found;
  360. }
  361. }
  362. } else {
  363. BUG();
  364. }
  365. found:
  366. if (!match) {
  367. if (min_fck_per_pck) {
  368. DSSERR("Could not find suitable clock settings.\n"
  369. "Turning FCK/PCK constraint off and"
  370. "trying again.\n");
  371. min_fck_per_pck = 0;
  372. goto retry;
  373. }
  374. DSSERR("Could not find suitable clock settings.\n");
  375. return -EINVAL;
  376. }
  377. if (dss_cinfo)
  378. *dss_cinfo = best_dss;
  379. if (dispc_cinfo)
  380. *dispc_cinfo = best_dispc;
  381. dss.cache_req_pck = req_pck;
  382. dss.cache_prate = prate;
  383. dss.cache_dss_cinfo = best_dss;
  384. dss.cache_dispc_cinfo = best_dispc;
  385. return 0;
  386. }
  387. static int _omap_dss_wait_reset(void)
  388. {
  389. int t = 0;
  390. while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
  391. if (++t > 1000) {
  392. DSSERR("soft reset failed\n");
  393. return -ENODEV;
  394. }
  395. udelay(1);
  396. }
  397. return 0;
  398. }
  399. static int _omap_dss_reset(void)
  400. {
  401. /* Soft reset */
  402. REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
  403. return _omap_dss_wait_reset();
  404. }
  405. void dss_set_venc_output(enum omap_dss_venc_type type)
  406. {
  407. int l = 0;
  408. if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
  409. l = 0;
  410. else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
  411. l = 1;
  412. else
  413. BUG();
  414. /* venc out selection. 0 = comp, 1 = svideo */
  415. REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
  416. }
  417. void dss_set_dac_pwrdn_bgz(bool enable)
  418. {
  419. REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
  420. }
  421. static int dss_init(bool skip_init)
  422. {
  423. int r;
  424. u32 rev;
  425. struct resource *dss_mem;
  426. dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
  427. if (!dss_mem) {
  428. DSSERR("can't get IORESOURCE_MEM DSS\n");
  429. r = -EINVAL;
  430. goto fail0;
  431. }
  432. dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
  433. if (!dss.base) {
  434. DSSERR("can't ioremap DSS\n");
  435. r = -ENOMEM;
  436. goto fail0;
  437. }
  438. if (!skip_init) {
  439. /* disable LCD and DIGIT output. This seems to fix the synclost
  440. * problem that we get, if the bootloader starts the DSS and
  441. * the kernel resets it */
  442. omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
  443. /* We need to wait here a bit, otherwise we sometimes start to
  444. * get synclost errors, and after that only power cycle will
  445. * restore DSS functionality. I have no idea why this happens.
  446. * And we have to wait _before_ resetting the DSS, but after
  447. * enabling clocks.
  448. */
  449. msleep(50);
  450. _omap_dss_reset();
  451. }
  452. /* autoidle */
  453. REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
  454. /* Select DPLL */
  455. REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
  456. #ifdef CONFIG_OMAP2_DSS_VENC
  457. REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
  458. REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
  459. REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
  460. #endif
  461. if (cpu_is_omap34xx()) {
  462. dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
  463. if (IS_ERR(dss.dpll4_m4_ck)) {
  464. DSSERR("Failed to get dpll4_m4_ck\n");
  465. r = PTR_ERR(dss.dpll4_m4_ck);
  466. goto fail1;
  467. }
  468. }
  469. dss.dsi_clk_source = DSS_SRC_DSS1_ALWON_FCLK;
  470. dss.dispc_clk_source = DSS_SRC_DSS1_ALWON_FCLK;
  471. dss_save_context();
  472. rev = dss_read_reg(DSS_REVISION);
  473. printk(KERN_INFO "OMAP DSS rev %d.%d\n",
  474. FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
  475. return 0;
  476. fail1:
  477. iounmap(dss.base);
  478. fail0:
  479. return r;
  480. }
  481. static void dss_exit(void)
  482. {
  483. if (cpu_is_omap34xx())
  484. clk_put(dss.dpll4_m4_ck);
  485. iounmap(dss.base);
  486. }
  487. /* CONTEXT */
  488. static int dss_get_ctx_id(void)
  489. {
  490. struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
  491. int r;
  492. if (!pdata->board_data->get_last_off_on_transaction_id)
  493. return 0;
  494. r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
  495. if (r < 0) {
  496. dev_err(&dss.pdev->dev, "getting transaction ID failed, "
  497. "will force context restore\n");
  498. r = -1;
  499. }
  500. return r;
  501. }
  502. int dss_need_ctx_restore(void)
  503. {
  504. int id = dss_get_ctx_id();
  505. if (id < 0 || id != dss.ctx_id) {
  506. DSSDBG("ctx id %d -> id %d\n",
  507. dss.ctx_id, id);
  508. dss.ctx_id = id;
  509. return 1;
  510. } else {
  511. return 0;
  512. }
  513. }
  514. static void save_all_ctx(void)
  515. {
  516. DSSDBG("save context\n");
  517. dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
  518. dss_save_context();
  519. dispc_save_context();
  520. #ifdef CONFIG_OMAP2_DSS_DSI
  521. dsi_save_context();
  522. #endif
  523. dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
  524. }
  525. static void restore_all_ctx(void)
  526. {
  527. DSSDBG("restore context\n");
  528. dss_clk_enable_all_no_ctx();
  529. dss_restore_context();
  530. dispc_restore_context();
  531. #ifdef CONFIG_OMAP2_DSS_DSI
  532. dsi_restore_context();
  533. #endif
  534. dss_clk_disable_all_no_ctx();
  535. }
  536. static int dss_get_clock(struct clk **clock, const char *clk_name)
  537. {
  538. struct clk *clk;
  539. clk = clk_get(&dss.pdev->dev, clk_name);
  540. if (IS_ERR(clk)) {
  541. DSSERR("can't get clock %s", clk_name);
  542. return PTR_ERR(clk);
  543. }
  544. *clock = clk;
  545. DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
  546. return 0;
  547. }
  548. static int dss_get_clocks(void)
  549. {
  550. int r;
  551. struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
  552. dss.dss_ick = NULL;
  553. dss.dss_fck = NULL;
  554. dss.dss_sys_clk = NULL;
  555. dss.dss_tv_fck = NULL;
  556. dss.dss_video_fck = NULL;
  557. r = dss_get_clock(&dss.dss_ick, "ick");
  558. if (r)
  559. goto err;
  560. r = dss_get_clock(&dss.dss_fck, "fck");
  561. if (r)
  562. goto err;
  563. if (!pdata->opt_clock_available) {
  564. r = -ENODEV;
  565. goto err;
  566. }
  567. if (pdata->opt_clock_available("sys_clk")) {
  568. r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
  569. if (r)
  570. goto err;
  571. }
  572. if (pdata->opt_clock_available("tv_clk")) {
  573. r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
  574. if (r)
  575. goto err;
  576. }
  577. if (pdata->opt_clock_available("video_clk")) {
  578. r = dss_get_clock(&dss.dss_video_fck, "video_clk");
  579. if (r)
  580. goto err;
  581. }
  582. return 0;
  583. err:
  584. if (dss.dss_ick)
  585. clk_put(dss.dss_ick);
  586. if (dss.dss_fck)
  587. clk_put(dss.dss_fck);
  588. if (dss.dss_sys_clk)
  589. clk_put(dss.dss_sys_clk);
  590. if (dss.dss_tv_fck)
  591. clk_put(dss.dss_tv_fck);
  592. if (dss.dss_video_fck)
  593. clk_put(dss.dss_video_fck);
  594. return r;
  595. }
  596. static void dss_put_clocks(void)
  597. {
  598. if (dss.dss_video_fck)
  599. clk_put(dss.dss_video_fck);
  600. if (dss.dss_tv_fck)
  601. clk_put(dss.dss_tv_fck);
  602. if (dss.dss_sys_clk)
  603. clk_put(dss.dss_sys_clk);
  604. clk_put(dss.dss_fck);
  605. clk_put(dss.dss_ick);
  606. }
  607. unsigned long dss_clk_get_rate(enum dss_clock clk)
  608. {
  609. switch (clk) {
  610. case DSS_CLK_ICK:
  611. return clk_get_rate(dss.dss_ick);
  612. case DSS_CLK_FCK:
  613. return clk_get_rate(dss.dss_fck);
  614. case DSS_CLK_SYSCK:
  615. return clk_get_rate(dss.dss_sys_clk);
  616. case DSS_CLK_TVFCK:
  617. return clk_get_rate(dss.dss_tv_fck);
  618. case DSS_CLK_VIDFCK:
  619. return clk_get_rate(dss.dss_video_fck);
  620. }
  621. BUG();
  622. return 0;
  623. }
  624. static unsigned count_clk_bits(enum dss_clock clks)
  625. {
  626. unsigned num_clks = 0;
  627. if (clks & DSS_CLK_ICK)
  628. ++num_clks;
  629. if (clks & DSS_CLK_FCK)
  630. ++num_clks;
  631. if (clks & DSS_CLK_SYSCK)
  632. ++num_clks;
  633. if (clks & DSS_CLK_TVFCK)
  634. ++num_clks;
  635. if (clks & DSS_CLK_VIDFCK)
  636. ++num_clks;
  637. return num_clks;
  638. }
  639. static void dss_clk_enable_no_ctx(enum dss_clock clks)
  640. {
  641. unsigned num_clks = count_clk_bits(clks);
  642. if (clks & DSS_CLK_ICK)
  643. clk_enable(dss.dss_ick);
  644. if (clks & DSS_CLK_FCK)
  645. clk_enable(dss.dss_fck);
  646. if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
  647. clk_enable(dss.dss_sys_clk);
  648. if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
  649. clk_enable(dss.dss_tv_fck);
  650. if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
  651. clk_enable(dss.dss_video_fck);
  652. dss.num_clks_enabled += num_clks;
  653. }
  654. void dss_clk_enable(enum dss_clock clks)
  655. {
  656. bool check_ctx = dss.num_clks_enabled == 0;
  657. dss_clk_enable_no_ctx(clks);
  658. if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
  659. restore_all_ctx();
  660. }
  661. static void dss_clk_disable_no_ctx(enum dss_clock clks)
  662. {
  663. unsigned num_clks = count_clk_bits(clks);
  664. if (clks & DSS_CLK_ICK)
  665. clk_disable(dss.dss_ick);
  666. if (clks & DSS_CLK_FCK)
  667. clk_disable(dss.dss_fck);
  668. if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
  669. clk_disable(dss.dss_sys_clk);
  670. if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
  671. clk_disable(dss.dss_tv_fck);
  672. if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
  673. clk_disable(dss.dss_video_fck);
  674. dss.num_clks_enabled -= num_clks;
  675. }
  676. void dss_clk_disable(enum dss_clock clks)
  677. {
  678. if (cpu_is_omap34xx()) {
  679. unsigned num_clks = count_clk_bits(clks);
  680. BUG_ON(dss.num_clks_enabled < num_clks);
  681. if (dss.num_clks_enabled == num_clks)
  682. save_all_ctx();
  683. }
  684. dss_clk_disable_no_ctx(clks);
  685. }
  686. static void dss_clk_enable_all_no_ctx(void)
  687. {
  688. enum dss_clock clks;
  689. clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
  690. if (cpu_is_omap34xx())
  691. clks |= DSS_CLK_VIDFCK;
  692. dss_clk_enable_no_ctx(clks);
  693. }
  694. static void dss_clk_disable_all_no_ctx(void)
  695. {
  696. enum dss_clock clks;
  697. clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
  698. if (cpu_is_omap34xx())
  699. clks |= DSS_CLK_VIDFCK;
  700. dss_clk_disable_no_ctx(clks);
  701. }
  702. #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
  703. /* CLOCKS */
  704. static void core_dump_clocks(struct seq_file *s)
  705. {
  706. int i;
  707. struct clk *clocks[5] = {
  708. dss.dss_ick,
  709. dss.dss_fck,
  710. dss.dss_sys_clk,
  711. dss.dss_tv_fck,
  712. dss.dss_video_fck
  713. };
  714. seq_printf(s, "- CORE -\n");
  715. seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
  716. for (i = 0; i < 5; i++) {
  717. if (!clocks[i])
  718. continue;
  719. seq_printf(s, "%-15s\t%lu\t%d\n",
  720. clocks[i]->name,
  721. clk_get_rate(clocks[i]),
  722. clocks[i]->usecount);
  723. }
  724. }
  725. #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
  726. /* DEBUGFS */
  727. #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
  728. void dss_debug_dump_clocks(struct seq_file *s)
  729. {
  730. core_dump_clocks(s);
  731. dss_dump_clocks(s);
  732. dispc_dump_clocks(s);
  733. #ifdef CONFIG_OMAP2_DSS_DSI
  734. dsi_dump_clocks(s);
  735. #endif
  736. }
  737. #endif
  738. /* DSS HW IP initialisation */
  739. static int omap_dsshw_probe(struct platform_device *pdev)
  740. {
  741. int r;
  742. int skip_init = 0;
  743. dss.pdev = pdev;
  744. r = dss_get_clocks();
  745. if (r)
  746. goto err_clocks;
  747. dss_clk_enable_all_no_ctx();
  748. dss.ctx_id = dss_get_ctx_id();
  749. DSSDBG("initial ctx id %u\n", dss.ctx_id);
  750. #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
  751. /* DISPC_CONTROL */
  752. if (omap_readl(0x48050440) & 1) /* LCD enabled? */
  753. skip_init = 1;
  754. #endif
  755. r = dss_init(skip_init);
  756. if (r) {
  757. DSSERR("Failed to initialize DSS\n");
  758. goto err_dss;
  759. }
  760. dss_clk_disable_all_no_ctx();
  761. return 0;
  762. err_dss:
  763. dss_clk_disable_all_no_ctx();
  764. dss_put_clocks();
  765. err_clocks:
  766. return r;
  767. }
  768. static int omap_dsshw_remove(struct platform_device *pdev)
  769. {
  770. dss_exit();
  771. /*
  772. * As part of hwmod changes, DSS is not the only controller of dss
  773. * clocks; hwmod framework itself will also enable clocks during hwmod
  774. * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
  775. * need to disable clocks if their usecounts > 1.
  776. */
  777. WARN_ON(dss.num_clks_enabled > 0);
  778. dss_put_clocks();
  779. return 0;
  780. }
  781. static struct platform_driver omap_dsshw_driver = {
  782. .probe = omap_dsshw_probe,
  783. .remove = omap_dsshw_remove,
  784. .driver = {
  785. .name = "omapdss_dss",
  786. .owner = THIS_MODULE,
  787. },
  788. };
  789. int dss_init_platform_driver(void)
  790. {
  791. return platform_driver_register(&omap_dsshw_driver);
  792. }
  793. void dss_uninit_platform_driver(void)
  794. {
  795. return platform_driver_unregister(&omap_dsshw_driver);
  796. }