hdmi_drv.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. /*
  2. * Samsung HDMI interface driver
  3. *
  4. * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  5. *
  6. * Tomasz Stanislawski, <t.stanislaws@samsung.com>
  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 as published
  10. * by the Free Software Foundiation. either version 2 of the License,
  11. * or (at your option) any later version
  12. */
  13. #ifdef CONFIG_VIDEO_SAMSUNG_S5P_HDMI_DEBUG
  14. #define DEBUG
  15. #endif
  16. #include <linux/kernel.h>
  17. #include <linux/slab.h>
  18. #include <linux/io.h>
  19. #include <linux/i2c.h>
  20. #include <linux/platform_device.h>
  21. #include <media/v4l2-subdev.h>
  22. #include <linux/module.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/irq.h>
  25. #include <linux/delay.h>
  26. #include <linux/bug.h>
  27. #include <linux/pm_runtime.h>
  28. #include <linux/clk.h>
  29. #include <linux/regulator/consumer.h>
  30. #include <media/v4l2-common.h>
  31. #include <media/v4l2-dev.h>
  32. #include <media/v4l2-device.h>
  33. #include "regs-hdmi.h"
  34. MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>");
  35. MODULE_DESCRIPTION("Samsung HDMI");
  36. MODULE_LICENSE("GPL");
  37. /* default preset configured on probe */
  38. #define HDMI_DEFAULT_PRESET V4L2_DV_1080P60
  39. struct hdmi_resources {
  40. struct clk *hdmi;
  41. struct clk *sclk_hdmi;
  42. struct clk *sclk_pixel;
  43. struct clk *sclk_hdmiphy;
  44. struct clk *hdmiphy;
  45. struct regulator_bulk_data *regul_bulk;
  46. int regul_count;
  47. };
  48. struct hdmi_device {
  49. /** base address of HDMI registers */
  50. void __iomem *regs;
  51. /** HDMI interrupt */
  52. unsigned int irq;
  53. /** pointer to device parent */
  54. struct device *dev;
  55. /** subdev generated by HDMI device */
  56. struct v4l2_subdev sd;
  57. /** V4L2 device structure */
  58. struct v4l2_device v4l2_dev;
  59. /** subdev of HDMIPHY interface */
  60. struct v4l2_subdev *phy_sd;
  61. /** configuration of current graphic mode */
  62. const struct hdmi_preset_conf *cur_conf;
  63. /** current preset */
  64. u32 cur_preset;
  65. /** other resources */
  66. struct hdmi_resources res;
  67. };
  68. struct hdmi_driver_data {
  69. int hdmiphy_bus;
  70. };
  71. struct hdmi_tg_regs {
  72. u8 cmd;
  73. u8 h_fsz_l;
  74. u8 h_fsz_h;
  75. u8 hact_st_l;
  76. u8 hact_st_h;
  77. u8 hact_sz_l;
  78. u8 hact_sz_h;
  79. u8 v_fsz_l;
  80. u8 v_fsz_h;
  81. u8 vsync_l;
  82. u8 vsync_h;
  83. u8 vsync2_l;
  84. u8 vsync2_h;
  85. u8 vact_st_l;
  86. u8 vact_st_h;
  87. u8 vact_sz_l;
  88. u8 vact_sz_h;
  89. u8 field_chg_l;
  90. u8 field_chg_h;
  91. u8 vact_st2_l;
  92. u8 vact_st2_h;
  93. u8 vsync_top_hdmi_l;
  94. u8 vsync_top_hdmi_h;
  95. u8 vsync_bot_hdmi_l;
  96. u8 vsync_bot_hdmi_h;
  97. u8 field_top_hdmi_l;
  98. u8 field_top_hdmi_h;
  99. u8 field_bot_hdmi_l;
  100. u8 field_bot_hdmi_h;
  101. };
  102. struct hdmi_core_regs {
  103. u8 h_blank[2];
  104. u8 v_blank[3];
  105. u8 h_v_line[3];
  106. u8 vsync_pol[1];
  107. u8 int_pro_mode[1];
  108. u8 v_blank_f[3];
  109. u8 h_sync_gen[3];
  110. u8 v_sync_gen1[3];
  111. u8 v_sync_gen2[3];
  112. u8 v_sync_gen3[3];
  113. };
  114. struct hdmi_preset_conf {
  115. struct hdmi_core_regs core;
  116. struct hdmi_tg_regs tg;
  117. struct v4l2_mbus_framefmt mbus_fmt;
  118. };
  119. /* I2C module and id for HDMIPHY */
  120. static struct i2c_board_info hdmiphy_info = {
  121. I2C_BOARD_INFO("hdmiphy", 0x38),
  122. };
  123. static struct hdmi_driver_data hdmi_driver_data[] = {
  124. { .hdmiphy_bus = 3 },
  125. { .hdmiphy_bus = 8 },
  126. };
  127. static struct platform_device_id hdmi_driver_types[] = {
  128. {
  129. .name = "s5pv210-hdmi",
  130. .driver_data = (unsigned long)&hdmi_driver_data[0],
  131. }, {
  132. .name = "exynos4-hdmi",
  133. .driver_data = (unsigned long)&hdmi_driver_data[1],
  134. }, {
  135. /* end node */
  136. }
  137. };
  138. static const struct v4l2_subdev_ops hdmi_sd_ops;
  139. static struct hdmi_device *sd_to_hdmi_dev(struct v4l2_subdev *sd)
  140. {
  141. return container_of(sd, struct hdmi_device, sd);
  142. }
  143. static inline
  144. void hdmi_write(struct hdmi_device *hdev, u32 reg_id, u32 value)
  145. {
  146. writel(value, hdev->regs + reg_id);
  147. }
  148. static inline
  149. void hdmi_write_mask(struct hdmi_device *hdev, u32 reg_id, u32 value, u32 mask)
  150. {
  151. u32 old = readl(hdev->regs + reg_id);
  152. value = (value & mask) | (old & ~mask);
  153. writel(value, hdev->regs + reg_id);
  154. }
  155. static inline
  156. void hdmi_writeb(struct hdmi_device *hdev, u32 reg_id, u8 value)
  157. {
  158. writeb(value, hdev->regs + reg_id);
  159. }
  160. static inline u32 hdmi_read(struct hdmi_device *hdev, u32 reg_id)
  161. {
  162. return readl(hdev->regs + reg_id);
  163. }
  164. static irqreturn_t hdmi_irq_handler(int irq, void *dev_data)
  165. {
  166. struct hdmi_device *hdev = dev_data;
  167. u32 intc_flag;
  168. (void)irq;
  169. intc_flag = hdmi_read(hdev, HDMI_INTC_FLAG);
  170. /* clearing flags for HPD plug/unplug */
  171. if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
  172. printk(KERN_INFO "unplugged\n");
  173. hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
  174. HDMI_INTC_FLAG_HPD_UNPLUG);
  175. }
  176. if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
  177. printk(KERN_INFO "plugged\n");
  178. hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
  179. HDMI_INTC_FLAG_HPD_PLUG);
  180. }
  181. return IRQ_HANDLED;
  182. }
  183. static void hdmi_reg_init(struct hdmi_device *hdev)
  184. {
  185. /* enable HPD interrupts */
  186. hdmi_write_mask(hdev, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
  187. HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
  188. /* choose DVI mode */
  189. hdmi_write_mask(hdev, HDMI_MODE_SEL,
  190. HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
  191. hdmi_write_mask(hdev, HDMI_CON_2, ~0,
  192. HDMI_DVI_PERAMBLE_EN | HDMI_DVI_BAND_EN);
  193. /* disable bluescreen */
  194. hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
  195. /* choose bluescreen (fecal) color */
  196. hdmi_writeb(hdev, HDMI_BLUE_SCREEN_0, 0x12);
  197. hdmi_writeb(hdev, HDMI_BLUE_SCREEN_1, 0x34);
  198. hdmi_writeb(hdev, HDMI_BLUE_SCREEN_2, 0x56);
  199. }
  200. static void hdmi_timing_apply(struct hdmi_device *hdev,
  201. const struct hdmi_preset_conf *conf)
  202. {
  203. const struct hdmi_core_regs *core = &conf->core;
  204. const struct hdmi_tg_regs *tg = &conf->tg;
  205. /* setting core registers */
  206. hdmi_writeb(hdev, HDMI_H_BLANK_0, core->h_blank[0]);
  207. hdmi_writeb(hdev, HDMI_H_BLANK_1, core->h_blank[1]);
  208. hdmi_writeb(hdev, HDMI_V_BLANK_0, core->v_blank[0]);
  209. hdmi_writeb(hdev, HDMI_V_BLANK_1, core->v_blank[1]);
  210. hdmi_writeb(hdev, HDMI_V_BLANK_2, core->v_blank[2]);
  211. hdmi_writeb(hdev, HDMI_H_V_LINE_0, core->h_v_line[0]);
  212. hdmi_writeb(hdev, HDMI_H_V_LINE_1, core->h_v_line[1]);
  213. hdmi_writeb(hdev, HDMI_H_V_LINE_2, core->h_v_line[2]);
  214. hdmi_writeb(hdev, HDMI_VSYNC_POL, core->vsync_pol[0]);
  215. hdmi_writeb(hdev, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
  216. hdmi_writeb(hdev, HDMI_V_BLANK_F_0, core->v_blank_f[0]);
  217. hdmi_writeb(hdev, HDMI_V_BLANK_F_1, core->v_blank_f[1]);
  218. hdmi_writeb(hdev, HDMI_V_BLANK_F_2, core->v_blank_f[2]);
  219. hdmi_writeb(hdev, HDMI_H_SYNC_GEN_0, core->h_sync_gen[0]);
  220. hdmi_writeb(hdev, HDMI_H_SYNC_GEN_1, core->h_sync_gen[1]);
  221. hdmi_writeb(hdev, HDMI_H_SYNC_GEN_2, core->h_sync_gen[2]);
  222. hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
  223. hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
  224. hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
  225. hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
  226. hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
  227. hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
  228. hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
  229. hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
  230. hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
  231. /* Timing generator registers */
  232. hdmi_writeb(hdev, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
  233. hdmi_writeb(hdev, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
  234. hdmi_writeb(hdev, HDMI_TG_HACT_ST_L, tg->hact_st_l);
  235. hdmi_writeb(hdev, HDMI_TG_HACT_ST_H, tg->hact_st_h);
  236. hdmi_writeb(hdev, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
  237. hdmi_writeb(hdev, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
  238. hdmi_writeb(hdev, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
  239. hdmi_writeb(hdev, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
  240. hdmi_writeb(hdev, HDMI_TG_VSYNC_L, tg->vsync_l);
  241. hdmi_writeb(hdev, HDMI_TG_VSYNC_H, tg->vsync_h);
  242. hdmi_writeb(hdev, HDMI_TG_VSYNC2_L, tg->vsync2_l);
  243. hdmi_writeb(hdev, HDMI_TG_VSYNC2_H, tg->vsync2_h);
  244. hdmi_writeb(hdev, HDMI_TG_VACT_ST_L, tg->vact_st_l);
  245. hdmi_writeb(hdev, HDMI_TG_VACT_ST_H, tg->vact_st_h);
  246. hdmi_writeb(hdev, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
  247. hdmi_writeb(hdev, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
  248. hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
  249. hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
  250. hdmi_writeb(hdev, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
  251. hdmi_writeb(hdev, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
  252. hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
  253. hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
  254. hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
  255. hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
  256. hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
  257. hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
  258. hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
  259. hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
  260. }
  261. static int hdmi_conf_apply(struct hdmi_device *hdmi_dev)
  262. {
  263. struct device *dev = hdmi_dev->dev;
  264. const struct hdmi_preset_conf *conf = hdmi_dev->cur_conf;
  265. struct v4l2_dv_preset preset;
  266. int ret;
  267. dev_dbg(dev, "%s\n", __func__);
  268. /* reset hdmiphy */
  269. hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
  270. mdelay(10);
  271. hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT);
  272. mdelay(10);
  273. /* configure presets */
  274. preset.preset = hdmi_dev->cur_preset;
  275. ret = v4l2_subdev_call(hdmi_dev->phy_sd, video, s_dv_preset, &preset);
  276. if (ret) {
  277. dev_err(dev, "failed to set preset (%u)\n", preset.preset);
  278. return ret;
  279. }
  280. /* resetting HDMI core */
  281. hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT, 0, HDMI_CORE_SW_RSTOUT);
  282. mdelay(10);
  283. hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT, ~0, HDMI_CORE_SW_RSTOUT);
  284. mdelay(10);
  285. hdmi_reg_init(hdmi_dev);
  286. /* setting core registers */
  287. hdmi_timing_apply(hdmi_dev, conf);
  288. return 0;
  289. }
  290. static void hdmi_dumpregs(struct hdmi_device *hdev, char *prefix)
  291. {
  292. #define DUMPREG(reg_id) \
  293. dev_dbg(hdev->dev, "%s:" #reg_id " = %08x\n", prefix, \
  294. readl(hdev->regs + reg_id))
  295. dev_dbg(hdev->dev, "%s: ---- CONTROL REGISTERS ----\n", prefix);
  296. DUMPREG(HDMI_INTC_FLAG);
  297. DUMPREG(HDMI_INTC_CON);
  298. DUMPREG(HDMI_HPD_STATUS);
  299. DUMPREG(HDMI_PHY_RSTOUT);
  300. DUMPREG(HDMI_PHY_VPLL);
  301. DUMPREG(HDMI_PHY_CMU);
  302. DUMPREG(HDMI_CORE_RSTOUT);
  303. dev_dbg(hdev->dev, "%s: ---- CORE REGISTERS ----\n", prefix);
  304. DUMPREG(HDMI_CON_0);
  305. DUMPREG(HDMI_CON_1);
  306. DUMPREG(HDMI_CON_2);
  307. DUMPREG(HDMI_SYS_STATUS);
  308. DUMPREG(HDMI_PHY_STATUS);
  309. DUMPREG(HDMI_STATUS_EN);
  310. DUMPREG(HDMI_HPD);
  311. DUMPREG(HDMI_MODE_SEL);
  312. DUMPREG(HDMI_HPD_GEN);
  313. DUMPREG(HDMI_DC_CONTROL);
  314. DUMPREG(HDMI_VIDEO_PATTERN_GEN);
  315. dev_dbg(hdev->dev, "%s: ---- CORE SYNC REGISTERS ----\n", prefix);
  316. DUMPREG(HDMI_H_BLANK_0);
  317. DUMPREG(HDMI_H_BLANK_1);
  318. DUMPREG(HDMI_V_BLANK_0);
  319. DUMPREG(HDMI_V_BLANK_1);
  320. DUMPREG(HDMI_V_BLANK_2);
  321. DUMPREG(HDMI_H_V_LINE_0);
  322. DUMPREG(HDMI_H_V_LINE_1);
  323. DUMPREG(HDMI_H_V_LINE_2);
  324. DUMPREG(HDMI_VSYNC_POL);
  325. DUMPREG(HDMI_INT_PRO_MODE);
  326. DUMPREG(HDMI_V_BLANK_F_0);
  327. DUMPREG(HDMI_V_BLANK_F_1);
  328. DUMPREG(HDMI_V_BLANK_F_2);
  329. DUMPREG(HDMI_H_SYNC_GEN_0);
  330. DUMPREG(HDMI_H_SYNC_GEN_1);
  331. DUMPREG(HDMI_H_SYNC_GEN_2);
  332. DUMPREG(HDMI_V_SYNC_GEN_1_0);
  333. DUMPREG(HDMI_V_SYNC_GEN_1_1);
  334. DUMPREG(HDMI_V_SYNC_GEN_1_2);
  335. DUMPREG(HDMI_V_SYNC_GEN_2_0);
  336. DUMPREG(HDMI_V_SYNC_GEN_2_1);
  337. DUMPREG(HDMI_V_SYNC_GEN_2_2);
  338. DUMPREG(HDMI_V_SYNC_GEN_3_0);
  339. DUMPREG(HDMI_V_SYNC_GEN_3_1);
  340. DUMPREG(HDMI_V_SYNC_GEN_3_2);
  341. dev_dbg(hdev->dev, "%s: ---- TG REGISTERS ----\n", prefix);
  342. DUMPREG(HDMI_TG_CMD);
  343. DUMPREG(HDMI_TG_H_FSZ_L);
  344. DUMPREG(HDMI_TG_H_FSZ_H);
  345. DUMPREG(HDMI_TG_HACT_ST_L);
  346. DUMPREG(HDMI_TG_HACT_ST_H);
  347. DUMPREG(HDMI_TG_HACT_SZ_L);
  348. DUMPREG(HDMI_TG_HACT_SZ_H);
  349. DUMPREG(HDMI_TG_V_FSZ_L);
  350. DUMPREG(HDMI_TG_V_FSZ_H);
  351. DUMPREG(HDMI_TG_VSYNC_L);
  352. DUMPREG(HDMI_TG_VSYNC_H);
  353. DUMPREG(HDMI_TG_VSYNC2_L);
  354. DUMPREG(HDMI_TG_VSYNC2_H);
  355. DUMPREG(HDMI_TG_VACT_ST_L);
  356. DUMPREG(HDMI_TG_VACT_ST_H);
  357. DUMPREG(HDMI_TG_VACT_SZ_L);
  358. DUMPREG(HDMI_TG_VACT_SZ_H);
  359. DUMPREG(HDMI_TG_FIELD_CHG_L);
  360. DUMPREG(HDMI_TG_FIELD_CHG_H);
  361. DUMPREG(HDMI_TG_VACT_ST2_L);
  362. DUMPREG(HDMI_TG_VACT_ST2_H);
  363. DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
  364. DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
  365. DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
  366. DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
  367. DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
  368. DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
  369. DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
  370. DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
  371. #undef DUMPREG
  372. }
  373. static const struct hdmi_preset_conf hdmi_conf_480p = {
  374. .core = {
  375. .h_blank = {0x8a, 0x00},
  376. .v_blank = {0x0d, 0x6a, 0x01},
  377. .h_v_line = {0x0d, 0xa2, 0x35},
  378. .vsync_pol = {0x01},
  379. .int_pro_mode = {0x00},
  380. .v_blank_f = {0x00, 0x00, 0x00},
  381. .h_sync_gen = {0x0e, 0x30, 0x11},
  382. .v_sync_gen1 = {0x0f, 0x90, 0x00},
  383. /* other don't care */
  384. },
  385. .tg = {
  386. 0x00, /* cmd */
  387. 0x5a, 0x03, /* h_fsz */
  388. 0x8a, 0x00, 0xd0, 0x02, /* hact */
  389. 0x0d, 0x02, /* v_fsz */
  390. 0x01, 0x00, 0x33, 0x02, /* vsync */
  391. 0x2d, 0x00, 0xe0, 0x01, /* vact */
  392. 0x33, 0x02, /* field_chg */
  393. 0x49, 0x02, /* vact_st2 */
  394. 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
  395. 0x01, 0x00, 0x33, 0x02, /* field top/bot */
  396. },
  397. .mbus_fmt = {
  398. .width = 720,
  399. .height = 480,
  400. .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
  401. .field = V4L2_FIELD_NONE,
  402. .colorspace = V4L2_COLORSPACE_SRGB,
  403. },
  404. };
  405. static const struct hdmi_preset_conf hdmi_conf_720p60 = {
  406. .core = {
  407. .h_blank = {0x72, 0x01},
  408. .v_blank = {0xee, 0xf2, 0x00},
  409. .h_v_line = {0xee, 0x22, 0x67},
  410. .vsync_pol = {0x00},
  411. .int_pro_mode = {0x00},
  412. .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
  413. .h_sync_gen = {0x6c, 0x50, 0x02},
  414. .v_sync_gen1 = {0x0a, 0x50, 0x00},
  415. /* other don't care */
  416. },
  417. .tg = {
  418. 0x00, /* cmd */
  419. 0x72, 0x06, /* h_fsz */
  420. 0x72, 0x01, 0x00, 0x05, /* hact */
  421. 0xee, 0x02, /* v_fsz */
  422. 0x01, 0x00, 0x33, 0x02, /* vsync */
  423. 0x1e, 0x00, 0xd0, 0x02, /* vact */
  424. 0x33, 0x02, /* field_chg */
  425. 0x49, 0x02, /* vact_st2 */
  426. 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
  427. 0x01, 0x00, 0x33, 0x02, /* field top/bot */
  428. },
  429. .mbus_fmt = {
  430. .width = 1280,
  431. .height = 720,
  432. .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
  433. .field = V4L2_FIELD_NONE,
  434. .colorspace = V4L2_COLORSPACE_SRGB,
  435. },
  436. };
  437. static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
  438. .core = {
  439. .h_blank = {0xd0, 0x02},
  440. .v_blank = {0x65, 0x6c, 0x01},
  441. .h_v_line = {0x65, 0x04, 0xa5},
  442. .vsync_pol = {0x00},
  443. .int_pro_mode = {0x00},
  444. .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
  445. .h_sync_gen = {0x0e, 0xea, 0x08},
  446. .v_sync_gen1 = {0x09, 0x40, 0x00},
  447. /* other don't care */
  448. },
  449. .tg = {
  450. 0x00, /* cmd */
  451. 0x98, 0x08, /* h_fsz */
  452. 0x18, 0x01, 0x80, 0x07, /* hact */
  453. 0x65, 0x04, /* v_fsz */
  454. 0x01, 0x00, 0x33, 0x02, /* vsync */
  455. 0x2d, 0x00, 0x38, 0x04, /* vact */
  456. 0x33, 0x02, /* field_chg */
  457. 0x49, 0x02, /* vact_st2 */
  458. 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
  459. 0x01, 0x00, 0x33, 0x02, /* field top/bot */
  460. },
  461. .mbus_fmt = {
  462. .width = 1920,
  463. .height = 1080,
  464. .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
  465. .field = V4L2_FIELD_NONE,
  466. .colorspace = V4L2_COLORSPACE_SRGB,
  467. },
  468. };
  469. static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
  470. .core = {
  471. .h_blank = {0x18, 0x01},
  472. .v_blank = {0x65, 0x6c, 0x01},
  473. .h_v_line = {0x65, 0x84, 0x89},
  474. .vsync_pol = {0x00},
  475. .int_pro_mode = {0x00},
  476. .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
  477. .h_sync_gen = {0x56, 0x08, 0x02},
  478. .v_sync_gen1 = {0x09, 0x40, 0x00},
  479. /* other don't care */
  480. },
  481. .tg = {
  482. 0x00, /* cmd */
  483. 0x98, 0x08, /* h_fsz */
  484. 0x18, 0x01, 0x80, 0x07, /* hact */
  485. 0x65, 0x04, /* v_fsz */
  486. 0x01, 0x00, 0x33, 0x02, /* vsync */
  487. 0x2d, 0x00, 0x38, 0x04, /* vact */
  488. 0x33, 0x02, /* field_chg */
  489. 0x48, 0x02, /* vact_st2 */
  490. 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
  491. 0x01, 0x00, 0x33, 0x02, /* field top/bot */
  492. },
  493. .mbus_fmt = {
  494. .width = 1920,
  495. .height = 1080,
  496. .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
  497. .field = V4L2_FIELD_NONE,
  498. .colorspace = V4L2_COLORSPACE_SRGB,
  499. },
  500. };
  501. static const struct {
  502. u32 preset;
  503. const struct hdmi_preset_conf *conf;
  504. } hdmi_conf[] = {
  505. { V4L2_DV_480P59_94, &hdmi_conf_480p },
  506. { V4L2_DV_720P59_94, &hdmi_conf_720p60 },
  507. { V4L2_DV_1080P50, &hdmi_conf_1080p50 },
  508. { V4L2_DV_1080P30, &hdmi_conf_1080p60 },
  509. { V4L2_DV_1080P60, &hdmi_conf_1080p60 },
  510. };
  511. static const struct hdmi_preset_conf *hdmi_preset2conf(u32 preset)
  512. {
  513. int i;
  514. for (i = 0; i < ARRAY_SIZE(hdmi_conf); ++i)
  515. if (hdmi_conf[i].preset == preset)
  516. return hdmi_conf[i].conf;
  517. return NULL;
  518. }
  519. static int hdmi_streamon(struct hdmi_device *hdev)
  520. {
  521. struct device *dev = hdev->dev;
  522. struct hdmi_resources *res = &hdev->res;
  523. int ret, tries;
  524. dev_dbg(dev, "%s\n", __func__);
  525. ret = v4l2_subdev_call(hdev->phy_sd, video, s_stream, 1);
  526. if (ret)
  527. return ret;
  528. /* waiting for HDMIPHY's PLL to get to steady state */
  529. for (tries = 100; tries; --tries) {
  530. u32 val = hdmi_read(hdev, HDMI_PHY_STATUS);
  531. if (val & HDMI_PHY_STATUS_READY)
  532. break;
  533. mdelay(1);
  534. }
  535. /* steady state not achieved */
  536. if (tries == 0) {
  537. dev_err(dev, "hdmiphy's pll could not reach steady state.\n");
  538. v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0);
  539. hdmi_dumpregs(hdev, "s_stream");
  540. return -EIO;
  541. }
  542. /* hdmiphy clock is used for HDMI in streaming mode */
  543. clk_disable(res->sclk_hdmi);
  544. clk_set_parent(res->sclk_hdmi, res->sclk_hdmiphy);
  545. clk_enable(res->sclk_hdmi);
  546. /* enable HDMI and timing generator */
  547. hdmi_write_mask(hdev, HDMI_CON_0, ~0, HDMI_EN);
  548. hdmi_write_mask(hdev, HDMI_TG_CMD, ~0, HDMI_TG_EN);
  549. hdmi_dumpregs(hdev, "streamon");
  550. return 0;
  551. }
  552. static int hdmi_streamoff(struct hdmi_device *hdev)
  553. {
  554. struct device *dev = hdev->dev;
  555. struct hdmi_resources *res = &hdev->res;
  556. dev_dbg(dev, "%s\n", __func__);
  557. hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_EN);
  558. hdmi_write_mask(hdev, HDMI_TG_CMD, 0, HDMI_TG_EN);
  559. /* pixel(vpll) clock is used for HDMI in config mode */
  560. clk_disable(res->sclk_hdmi);
  561. clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
  562. clk_enable(res->sclk_hdmi);
  563. v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0);
  564. hdmi_dumpregs(hdev, "streamoff");
  565. return 0;
  566. }
  567. static int hdmi_s_stream(struct v4l2_subdev *sd, int enable)
  568. {
  569. struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
  570. struct device *dev = hdev->dev;
  571. dev_dbg(dev, "%s(%d)\n", __func__, enable);
  572. if (enable)
  573. return hdmi_streamon(hdev);
  574. return hdmi_streamoff(hdev);
  575. }
  576. static void hdmi_resource_poweron(struct hdmi_resources *res)
  577. {
  578. /* turn HDMI power on */
  579. regulator_bulk_enable(res->regul_count, res->regul_bulk);
  580. /* power-on hdmi physical interface */
  581. clk_enable(res->hdmiphy);
  582. /* use VPP as parent clock; HDMIPHY is not working yet */
  583. clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
  584. /* turn clocks on */
  585. clk_enable(res->sclk_hdmi);
  586. }
  587. static void hdmi_resource_poweroff(struct hdmi_resources *res)
  588. {
  589. /* turn clocks off */
  590. clk_disable(res->sclk_hdmi);
  591. /* power-off hdmiphy */
  592. clk_disable(res->hdmiphy);
  593. /* turn HDMI power off */
  594. regulator_bulk_disable(res->regul_count, res->regul_bulk);
  595. }
  596. static int hdmi_s_power(struct v4l2_subdev *sd, int on)
  597. {
  598. struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
  599. int ret;
  600. if (on)
  601. ret = pm_runtime_get_sync(hdev->dev);
  602. else
  603. ret = pm_runtime_put_sync(hdev->dev);
  604. /* only values < 0 indicate errors */
  605. return IS_ERR_VALUE(ret) ? ret : 0;
  606. }
  607. static int hdmi_s_dv_preset(struct v4l2_subdev *sd,
  608. struct v4l2_dv_preset *preset)
  609. {
  610. struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
  611. struct device *dev = hdev->dev;
  612. const struct hdmi_preset_conf *conf;
  613. conf = hdmi_preset2conf(preset->preset);
  614. if (conf == NULL) {
  615. dev_err(dev, "preset (%u) not supported\n", preset->preset);
  616. return -EINVAL;
  617. }
  618. hdev->cur_conf = conf;
  619. hdev->cur_preset = preset->preset;
  620. return 0;
  621. }
  622. static int hdmi_g_dv_preset(struct v4l2_subdev *sd,
  623. struct v4l2_dv_preset *preset)
  624. {
  625. memset(preset, 0, sizeof(*preset));
  626. preset->preset = sd_to_hdmi_dev(sd)->cur_preset;
  627. return 0;
  628. }
  629. static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd,
  630. struct v4l2_mbus_framefmt *fmt)
  631. {
  632. struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
  633. struct device *dev = hdev->dev;
  634. dev_dbg(dev, "%s\n", __func__);
  635. if (!hdev->cur_conf)
  636. return -EINVAL;
  637. *fmt = hdev->cur_conf->mbus_fmt;
  638. return 0;
  639. }
  640. static int hdmi_enum_dv_presets(struct v4l2_subdev *sd,
  641. struct v4l2_dv_enum_preset *preset)
  642. {
  643. if (preset->index >= ARRAY_SIZE(hdmi_conf))
  644. return -EINVAL;
  645. return v4l_fill_dv_preset_info(hdmi_conf[preset->index].preset, preset);
  646. }
  647. static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = {
  648. .s_power = hdmi_s_power,
  649. };
  650. static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = {
  651. .s_dv_preset = hdmi_s_dv_preset,
  652. .g_dv_preset = hdmi_g_dv_preset,
  653. .enum_dv_presets = hdmi_enum_dv_presets,
  654. .g_mbus_fmt = hdmi_g_mbus_fmt,
  655. .s_stream = hdmi_s_stream,
  656. };
  657. static const struct v4l2_subdev_ops hdmi_sd_ops = {
  658. .core = &hdmi_sd_core_ops,
  659. .video = &hdmi_sd_video_ops,
  660. };
  661. static int hdmi_runtime_suspend(struct device *dev)
  662. {
  663. struct v4l2_subdev *sd = dev_get_drvdata(dev);
  664. struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
  665. dev_dbg(dev, "%s\n", __func__);
  666. hdmi_resource_poweroff(&hdev->res);
  667. return 0;
  668. }
  669. static int hdmi_runtime_resume(struct device *dev)
  670. {
  671. struct v4l2_subdev *sd = dev_get_drvdata(dev);
  672. struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
  673. int ret = 0;
  674. dev_dbg(dev, "%s\n", __func__);
  675. hdmi_resource_poweron(&hdev->res);
  676. ret = hdmi_conf_apply(hdev);
  677. if (ret)
  678. goto fail;
  679. dev_dbg(dev, "poweron succeed\n");
  680. return 0;
  681. fail:
  682. hdmi_resource_poweroff(&hdev->res);
  683. dev_err(dev, "poweron failed\n");
  684. return ret;
  685. }
  686. static const struct dev_pm_ops hdmi_pm_ops = {
  687. .runtime_suspend = hdmi_runtime_suspend,
  688. .runtime_resume = hdmi_runtime_resume,
  689. };
  690. static void hdmi_resources_cleanup(struct hdmi_device *hdev)
  691. {
  692. struct hdmi_resources *res = &hdev->res;
  693. dev_dbg(hdev->dev, "HDMI resource cleanup\n");
  694. /* put clocks, power */
  695. if (res->regul_count)
  696. regulator_bulk_free(res->regul_count, res->regul_bulk);
  697. /* kfree is NULL-safe */
  698. kfree(res->regul_bulk);
  699. if (!IS_ERR_OR_NULL(res->hdmiphy))
  700. clk_put(res->hdmiphy);
  701. if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
  702. clk_put(res->sclk_hdmiphy);
  703. if (!IS_ERR_OR_NULL(res->sclk_pixel))
  704. clk_put(res->sclk_pixel);
  705. if (!IS_ERR_OR_NULL(res->sclk_hdmi))
  706. clk_put(res->sclk_hdmi);
  707. if (!IS_ERR_OR_NULL(res->hdmi))
  708. clk_put(res->hdmi);
  709. memset(res, 0, sizeof *res);
  710. }
  711. static int hdmi_resources_init(struct hdmi_device *hdev)
  712. {
  713. struct device *dev = hdev->dev;
  714. struct hdmi_resources *res = &hdev->res;
  715. static char *supply[] = {
  716. "hdmi-en",
  717. "vdd",
  718. "vdd_osc",
  719. "vdd_pll",
  720. };
  721. int i, ret;
  722. dev_dbg(dev, "HDMI resource init\n");
  723. memset(res, 0, sizeof *res);
  724. /* get clocks, power */
  725. res->hdmi = clk_get(dev, "hdmi");
  726. if (IS_ERR_OR_NULL(res->hdmi)) {
  727. dev_err(dev, "failed to get clock 'hdmi'\n");
  728. goto fail;
  729. }
  730. res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
  731. if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
  732. dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
  733. goto fail;
  734. }
  735. res->sclk_pixel = clk_get(dev, "sclk_pixel");
  736. if (IS_ERR_OR_NULL(res->sclk_pixel)) {
  737. dev_err(dev, "failed to get clock 'sclk_pixel'\n");
  738. goto fail;
  739. }
  740. res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
  741. if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
  742. dev_err(dev, "failed to get clock 'sclk_hdmiphy'\n");
  743. goto fail;
  744. }
  745. res->hdmiphy = clk_get(dev, "hdmiphy");
  746. if (IS_ERR_OR_NULL(res->hdmiphy)) {
  747. dev_err(dev, "failed to get clock 'hdmiphy'\n");
  748. goto fail;
  749. }
  750. res->regul_bulk = kcalloc(ARRAY_SIZE(supply),
  751. sizeof(res->regul_bulk[0]), GFP_KERNEL);
  752. if (!res->regul_bulk) {
  753. dev_err(dev, "failed to get memory for regulators\n");
  754. goto fail;
  755. }
  756. for (i = 0; i < ARRAY_SIZE(supply); ++i) {
  757. res->regul_bulk[i].supply = supply[i];
  758. res->regul_bulk[i].consumer = NULL;
  759. }
  760. ret = regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
  761. if (ret) {
  762. dev_err(dev, "failed to get regulators\n");
  763. goto fail;
  764. }
  765. res->regul_count = ARRAY_SIZE(supply);
  766. return 0;
  767. fail:
  768. dev_err(dev, "HDMI resource init - failed\n");
  769. hdmi_resources_cleanup(hdev);
  770. return -ENODEV;
  771. }
  772. static int __devinit hdmi_probe(struct platform_device *pdev)
  773. {
  774. struct device *dev = &pdev->dev;
  775. struct resource *res;
  776. struct i2c_adapter *phy_adapter;
  777. struct v4l2_subdev *sd;
  778. struct hdmi_device *hdmi_dev = NULL;
  779. struct hdmi_driver_data *drv_data;
  780. int ret;
  781. dev_dbg(dev, "probe start\n");
  782. hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(*hdmi_dev), GFP_KERNEL);
  783. if (!hdmi_dev) {
  784. dev_err(dev, "out of memory\n");
  785. ret = -ENOMEM;
  786. goto fail;
  787. }
  788. hdmi_dev->dev = dev;
  789. ret = hdmi_resources_init(hdmi_dev);
  790. if (ret)
  791. goto fail;
  792. /* mapping HDMI registers */
  793. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  794. if (res == NULL) {
  795. dev_err(dev, "get memory resource failed.\n");
  796. ret = -ENXIO;
  797. goto fail_init;
  798. }
  799. hdmi_dev->regs = devm_ioremap(&pdev->dev, res->start,
  800. resource_size(res));
  801. if (hdmi_dev->regs == NULL) {
  802. dev_err(dev, "register mapping failed.\n");
  803. ret = -ENXIO;
  804. goto fail_init;
  805. }
  806. res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  807. if (res == NULL) {
  808. dev_err(dev, "get interrupt resource failed.\n");
  809. ret = -ENXIO;
  810. goto fail_init;
  811. }
  812. ret = devm_request_irq(&pdev->dev, res->start, hdmi_irq_handler, 0,
  813. "hdmi", hdmi_dev);
  814. if (ret) {
  815. dev_err(dev, "request interrupt failed.\n");
  816. goto fail_init;
  817. }
  818. hdmi_dev->irq = res->start;
  819. /* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
  820. strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
  821. sizeof(hdmi_dev->v4l2_dev.name));
  822. /* passing NULL owner prevents driver from erasing drvdata */
  823. ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
  824. if (ret) {
  825. dev_err(dev, "could not register v4l2 device.\n");
  826. goto fail_init;
  827. }
  828. drv_data = (struct hdmi_driver_data *)
  829. platform_get_device_id(pdev)->driver_data;
  830. phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus);
  831. if (phy_adapter == NULL) {
  832. dev_err(dev, "adapter request failed\n");
  833. ret = -ENXIO;
  834. goto fail_vdev;
  835. }
  836. hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
  837. phy_adapter, &hdmiphy_info, NULL);
  838. /* on failure or not adapter is no longer useful */
  839. i2c_put_adapter(phy_adapter);
  840. if (hdmi_dev->phy_sd == NULL) {
  841. dev_err(dev, "missing subdev for hdmiphy\n");
  842. ret = -ENODEV;
  843. goto fail_vdev;
  844. }
  845. clk_enable(hdmi_dev->res.hdmi);
  846. pm_runtime_enable(dev);
  847. sd = &hdmi_dev->sd;
  848. v4l2_subdev_init(sd, &hdmi_sd_ops);
  849. sd->owner = THIS_MODULE;
  850. strlcpy(sd->name, "s5p-hdmi", sizeof sd->name);
  851. hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
  852. /* FIXME: missing fail preset is not supported */
  853. hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset);
  854. /* storing subdev for call that have only access to struct device */
  855. dev_set_drvdata(dev, sd);
  856. dev_info(dev, "probe successful\n");
  857. return 0;
  858. fail_vdev:
  859. v4l2_device_unregister(&hdmi_dev->v4l2_dev);
  860. fail_init:
  861. hdmi_resources_cleanup(hdmi_dev);
  862. fail:
  863. dev_err(dev, "probe failed\n");
  864. return ret;
  865. }
  866. static int __devexit hdmi_remove(struct platform_device *pdev)
  867. {
  868. struct device *dev = &pdev->dev;
  869. struct v4l2_subdev *sd = dev_get_drvdata(dev);
  870. struct hdmi_device *hdmi_dev = sd_to_hdmi_dev(sd);
  871. pm_runtime_disable(dev);
  872. clk_disable(hdmi_dev->res.hdmi);
  873. v4l2_device_unregister(&hdmi_dev->v4l2_dev);
  874. disable_irq(hdmi_dev->irq);
  875. hdmi_resources_cleanup(hdmi_dev);
  876. dev_info(dev, "remove successful\n");
  877. return 0;
  878. }
  879. static struct platform_driver hdmi_driver __refdata = {
  880. .probe = hdmi_probe,
  881. .remove = __devexit_p(hdmi_remove),
  882. .id_table = hdmi_driver_types,
  883. .driver = {
  884. .name = "s5p-hdmi",
  885. .owner = THIS_MODULE,
  886. .pm = &hdmi_pm_ops,
  887. }
  888. };
  889. module_platform_driver(hdmi_driver);