zx_vou.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. /*
  2. * Copyright 2016 Linaro Ltd.
  3. * Copyright 2016 ZTE Corporation.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. */
  10. #include <linux/clk.h>
  11. #include <linux/component.h>
  12. #include <linux/of_address.h>
  13. #include <video/videomode.h>
  14. #include <drm/drm_atomic_helper.h>
  15. #include <drm/drm_crtc.h>
  16. #include <drm/drm_crtc_helper.h>
  17. #include <drm/drm_fb_cma_helper.h>
  18. #include <drm/drm_fb_helper.h>
  19. #include <drm/drm_gem_cma_helper.h>
  20. #include <drm/drm_of.h>
  21. #include <drm/drm_plane_helper.h>
  22. #include <drm/drmP.h>
  23. #include "zx_drm_drv.h"
  24. #include "zx_plane.h"
  25. #include "zx_vou.h"
  26. #include "zx_vou_regs.h"
  27. #define GL_NUM 2
  28. #define VL_NUM 3
  29. enum vou_chn_type {
  30. VOU_CHN_MAIN,
  31. VOU_CHN_AUX,
  32. };
  33. struct zx_crtc_regs {
  34. u32 fir_active;
  35. u32 fir_htiming;
  36. u32 fir_vtiming;
  37. u32 timing_shift;
  38. u32 timing_pi_shift;
  39. };
  40. static const struct zx_crtc_regs main_crtc_regs = {
  41. .fir_active = FIR_MAIN_ACTIVE,
  42. .fir_htiming = FIR_MAIN_H_TIMING,
  43. .fir_vtiming = FIR_MAIN_V_TIMING,
  44. .timing_shift = TIMING_MAIN_SHIFT,
  45. .timing_pi_shift = TIMING_MAIN_PI_SHIFT,
  46. };
  47. static const struct zx_crtc_regs aux_crtc_regs = {
  48. .fir_active = FIR_AUX_ACTIVE,
  49. .fir_htiming = FIR_AUX_H_TIMING,
  50. .fir_vtiming = FIR_AUX_V_TIMING,
  51. .timing_shift = TIMING_AUX_SHIFT,
  52. .timing_pi_shift = TIMING_AUX_PI_SHIFT,
  53. };
  54. struct zx_crtc_bits {
  55. u32 polarity_mask;
  56. u32 polarity_shift;
  57. u32 int_frame_mask;
  58. u32 tc_enable;
  59. u32 gl_enable;
  60. };
  61. static const struct zx_crtc_bits main_crtc_bits = {
  62. .polarity_mask = MAIN_POL_MASK,
  63. .polarity_shift = MAIN_POL_SHIFT,
  64. .int_frame_mask = TIMING_INT_MAIN_FRAME,
  65. .tc_enable = MAIN_TC_EN,
  66. .gl_enable = OSD_CTRL0_GL0_EN,
  67. };
  68. static const struct zx_crtc_bits aux_crtc_bits = {
  69. .polarity_mask = AUX_POL_MASK,
  70. .polarity_shift = AUX_POL_SHIFT,
  71. .int_frame_mask = TIMING_INT_AUX_FRAME,
  72. .tc_enable = AUX_TC_EN,
  73. .gl_enable = OSD_CTRL0_GL1_EN,
  74. };
  75. struct zx_crtc {
  76. struct drm_crtc crtc;
  77. struct drm_plane *primary;
  78. struct zx_vou_hw *vou;
  79. void __iomem *chnreg;
  80. const struct zx_crtc_regs *regs;
  81. const struct zx_crtc_bits *bits;
  82. enum vou_chn_type chn_type;
  83. struct clk *pixclk;
  84. };
  85. #define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
  86. struct zx_vou_hw {
  87. struct device *dev;
  88. void __iomem *osd;
  89. void __iomem *timing;
  90. void __iomem *vouctl;
  91. void __iomem *otfppu;
  92. void __iomem *dtrc;
  93. struct clk *axi_clk;
  94. struct clk *ppu_clk;
  95. struct clk *main_clk;
  96. struct clk *aux_clk;
  97. struct zx_crtc *main_crtc;
  98. struct zx_crtc *aux_crtc;
  99. };
  100. static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc)
  101. {
  102. struct zx_crtc *zcrtc = to_zx_crtc(crtc);
  103. return zcrtc->vou;
  104. }
  105. void vou_inf_enable(const struct vou_inf *inf, struct drm_crtc *crtc)
  106. {
  107. struct zx_crtc *zcrtc = to_zx_crtc(crtc);
  108. struct zx_vou_hw *vou = zcrtc->vou;
  109. bool is_main = zcrtc->chn_type == VOU_CHN_MAIN;
  110. u32 data_sel_shift = inf->id << 1;
  111. /* Select data format */
  112. zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift,
  113. inf->data_sel << data_sel_shift);
  114. /* Select channel */
  115. zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << inf->id,
  116. zcrtc->chn_type << inf->id);
  117. /* Select interface clocks */
  118. zx_writel_mask(vou->vouctl + VOU_CLK_SEL, inf->clocks_sel_bits,
  119. is_main ? 0 : inf->clocks_sel_bits);
  120. /* Enable interface clocks */
  121. zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits,
  122. inf->clocks_en_bits);
  123. /* Enable the device */
  124. zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << inf->id, 1 << inf->id);
  125. }
  126. void vou_inf_disable(const struct vou_inf *inf, struct drm_crtc *crtc)
  127. {
  128. struct zx_vou_hw *vou = crtc_to_vou(crtc);
  129. /* Disable the device */
  130. zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << inf->id, 0);
  131. /* Disable interface clocks */
  132. zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0);
  133. }
  134. static inline void vou_chn_set_update(struct zx_crtc *zcrtc)
  135. {
  136. zx_writel(zcrtc->chnreg + CHN_UPDATE, 1);
  137. }
  138. static void zx_crtc_enable(struct drm_crtc *crtc)
  139. {
  140. struct drm_display_mode *mode = &crtc->state->adjusted_mode;
  141. struct zx_crtc *zcrtc = to_zx_crtc(crtc);
  142. struct zx_vou_hw *vou = zcrtc->vou;
  143. const struct zx_crtc_regs *regs = zcrtc->regs;
  144. const struct zx_crtc_bits *bits = zcrtc->bits;
  145. struct videomode vm;
  146. u32 pol = 0;
  147. u32 val;
  148. int ret;
  149. drm_display_mode_to_videomode(mode, &vm);
  150. /* Set up timing parameters */
  151. val = V_ACTIVE(vm.vactive - 1);
  152. val |= H_ACTIVE(vm.hactive - 1);
  153. zx_writel(vou->timing + regs->fir_active, val);
  154. val = SYNC_WIDE(vm.hsync_len - 1);
  155. val |= BACK_PORCH(vm.hback_porch - 1);
  156. val |= FRONT_PORCH(vm.hfront_porch - 1);
  157. zx_writel(vou->timing + regs->fir_htiming, val);
  158. val = SYNC_WIDE(vm.vsync_len - 1);
  159. val |= BACK_PORCH(vm.vback_porch - 1);
  160. val |= FRONT_PORCH(vm.vfront_porch - 1);
  161. zx_writel(vou->timing + regs->fir_vtiming, val);
  162. /* Set up polarities */
  163. if (vm.flags & DISPLAY_FLAGS_VSYNC_LOW)
  164. pol |= 1 << POL_VSYNC_SHIFT;
  165. if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW)
  166. pol |= 1 << POL_HSYNC_SHIFT;
  167. zx_writel_mask(vou->timing + TIMING_CTRL, bits->polarity_mask,
  168. pol << bits->polarity_shift);
  169. /* Setup SHIFT register by following what ZTE BSP does */
  170. zx_writel(vou->timing + regs->timing_shift, H_SHIFT_VAL);
  171. zx_writel(vou->timing + regs->timing_pi_shift, H_PI_SHIFT_VAL);
  172. /* Enable TIMING_CTRL */
  173. zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable,
  174. bits->tc_enable);
  175. /* Configure channel screen size */
  176. zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_W_MASK,
  177. vm.hactive << CHN_SCREEN_W_SHIFT);
  178. zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_H_MASK,
  179. vm.vactive << CHN_SCREEN_H_SHIFT);
  180. /* Update channel */
  181. vou_chn_set_update(zcrtc);
  182. /* Enable channel */
  183. zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE);
  184. /* Enable Graphic Layer */
  185. zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable,
  186. bits->gl_enable);
  187. drm_crtc_vblank_on(crtc);
  188. ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000);
  189. if (ret) {
  190. DRM_DEV_ERROR(vou->dev, "failed to set pixclk rate: %d\n", ret);
  191. return;
  192. }
  193. ret = clk_prepare_enable(zcrtc->pixclk);
  194. if (ret)
  195. DRM_DEV_ERROR(vou->dev, "failed to enable pixclk: %d\n", ret);
  196. }
  197. static void zx_crtc_disable(struct drm_crtc *crtc)
  198. {
  199. struct zx_crtc *zcrtc = to_zx_crtc(crtc);
  200. const struct zx_crtc_bits *bits = zcrtc->bits;
  201. struct zx_vou_hw *vou = zcrtc->vou;
  202. clk_disable_unprepare(zcrtc->pixclk);
  203. drm_crtc_vblank_off(crtc);
  204. /* Disable Graphic Layer */
  205. zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable, 0);
  206. /* Disable channel */
  207. zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
  208. /* Disable TIMING_CTRL */
  209. zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 0);
  210. }
  211. static void zx_crtc_atomic_flush(struct drm_crtc *crtc,
  212. struct drm_crtc_state *old_state)
  213. {
  214. struct drm_pending_vblank_event *event = crtc->state->event;
  215. if (!event)
  216. return;
  217. crtc->state->event = NULL;
  218. spin_lock_irq(&crtc->dev->event_lock);
  219. if (drm_crtc_vblank_get(crtc) == 0)
  220. drm_crtc_arm_vblank_event(crtc, event);
  221. else
  222. drm_crtc_send_vblank_event(crtc, event);
  223. spin_unlock_irq(&crtc->dev->event_lock);
  224. }
  225. static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = {
  226. .enable = zx_crtc_enable,
  227. .disable = zx_crtc_disable,
  228. .atomic_flush = zx_crtc_atomic_flush,
  229. };
  230. static const struct drm_crtc_funcs zx_crtc_funcs = {
  231. .destroy = drm_crtc_cleanup,
  232. .set_config = drm_atomic_helper_set_config,
  233. .page_flip = drm_atomic_helper_page_flip,
  234. .reset = drm_atomic_helper_crtc_reset,
  235. .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
  236. .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
  237. };
  238. static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
  239. enum vou_chn_type chn_type)
  240. {
  241. struct device *dev = vou->dev;
  242. struct zx_layer_data data;
  243. struct zx_crtc *zcrtc;
  244. int ret;
  245. zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
  246. if (!zcrtc)
  247. return -ENOMEM;
  248. zcrtc->vou = vou;
  249. zcrtc->chn_type = chn_type;
  250. if (chn_type == VOU_CHN_MAIN) {
  251. data.layer = vou->osd + MAIN_GL_OFFSET;
  252. data.csc = vou->osd + MAIN_CSC_OFFSET;
  253. data.hbsc = vou->osd + MAIN_HBSC_OFFSET;
  254. data.rsz = vou->otfppu + MAIN_RSZ_OFFSET;
  255. zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
  256. zcrtc->regs = &main_crtc_regs;
  257. zcrtc->bits = &main_crtc_bits;
  258. } else {
  259. data.layer = vou->osd + AUX_GL_OFFSET;
  260. data.csc = vou->osd + AUX_CSC_OFFSET;
  261. data.hbsc = vou->osd + AUX_HBSC_OFFSET;
  262. data.rsz = vou->otfppu + AUX_RSZ_OFFSET;
  263. zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
  264. zcrtc->regs = &aux_crtc_regs;
  265. zcrtc->bits = &aux_crtc_bits;
  266. }
  267. zcrtc->pixclk = devm_clk_get(dev, (chn_type == VOU_CHN_MAIN) ?
  268. "main_wclk" : "aux_wclk");
  269. if (IS_ERR(zcrtc->pixclk)) {
  270. ret = PTR_ERR(zcrtc->pixclk);
  271. DRM_DEV_ERROR(dev, "failed to get pix clk: %d\n", ret);
  272. return ret;
  273. }
  274. zcrtc->primary = zx_plane_init(drm, dev, &data, DRM_PLANE_TYPE_PRIMARY);
  275. if (IS_ERR(zcrtc->primary)) {
  276. ret = PTR_ERR(zcrtc->primary);
  277. DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
  278. return ret;
  279. }
  280. ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
  281. &zx_crtc_funcs, NULL);
  282. if (ret) {
  283. DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret);
  284. return ret;
  285. }
  286. drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs);
  287. if (chn_type == VOU_CHN_MAIN)
  288. vou->main_crtc = zcrtc;
  289. else
  290. vou->aux_crtc = zcrtc;
  291. return 0;
  292. }
  293. int zx_vou_enable_vblank(struct drm_device *drm, unsigned int pipe)
  294. {
  295. struct drm_crtc *crtc;
  296. struct zx_crtc *zcrtc;
  297. struct zx_vou_hw *vou;
  298. u32 int_frame_mask;
  299. crtc = drm_crtc_from_index(drm, pipe);
  300. if (!crtc)
  301. return 0;
  302. vou = crtc_to_vou(crtc);
  303. zcrtc = to_zx_crtc(crtc);
  304. int_frame_mask = zcrtc->bits->int_frame_mask;
  305. zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
  306. int_frame_mask);
  307. return 0;
  308. }
  309. void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe)
  310. {
  311. struct drm_crtc *crtc;
  312. struct zx_crtc *zcrtc;
  313. struct zx_vou_hw *vou;
  314. crtc = drm_crtc_from_index(drm, pipe);
  315. if (!crtc)
  316. return;
  317. vou = crtc_to_vou(crtc);
  318. zcrtc = to_zx_crtc(crtc);
  319. zx_writel_mask(vou->timing + TIMING_INT_CTRL,
  320. zcrtc->bits->int_frame_mask, 0);
  321. }
  322. static irqreturn_t vou_irq_handler(int irq, void *dev_id)
  323. {
  324. struct zx_vou_hw *vou = dev_id;
  325. u32 state;
  326. /* Handle TIMING_CTRL frame interrupts */
  327. state = zx_readl(vou->timing + TIMING_INT_STATE);
  328. zx_writel(vou->timing + TIMING_INT_STATE, state);
  329. if (state & TIMING_INT_MAIN_FRAME)
  330. drm_crtc_handle_vblank(&vou->main_crtc->crtc);
  331. if (state & TIMING_INT_AUX_FRAME)
  332. drm_crtc_handle_vblank(&vou->aux_crtc->crtc);
  333. /* Handle OSD interrupts */
  334. state = zx_readl(vou->osd + OSD_INT_STA);
  335. zx_writel(vou->osd + OSD_INT_CLRSTA, state);
  336. if (state & OSD_INT_MAIN_UPT) {
  337. vou_chn_set_update(vou->main_crtc);
  338. zx_plane_set_update(vou->main_crtc->primary);
  339. }
  340. if (state & OSD_INT_AUX_UPT) {
  341. vou_chn_set_update(vou->aux_crtc);
  342. zx_plane_set_update(vou->aux_crtc->primary);
  343. }
  344. if (state & OSD_INT_ERROR)
  345. DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state);
  346. return IRQ_HANDLED;
  347. }
  348. static void vou_dtrc_init(struct zx_vou_hw *vou)
  349. {
  350. /* Clear bit for bypass by ID */
  351. zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL,
  352. TILE2RASTESCAN_BYPASS_MODE, 0);
  353. /* Select ARIDR mode */
  354. zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK,
  355. DETILE_ARID_IN_ARIDR);
  356. /* Bypass decompression for both frames */
  357. zx_writel_mask(vou->dtrc + DTRC_F0_CTRL, DTRC_DECOMPRESS_BYPASS,
  358. DTRC_DECOMPRESS_BYPASS);
  359. zx_writel_mask(vou->dtrc + DTRC_F1_CTRL, DTRC_DECOMPRESS_BYPASS,
  360. DTRC_DECOMPRESS_BYPASS);
  361. /* Set up ARID register */
  362. zx_writel(vou->dtrc + DTRC_ARID, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) |
  363. DTRC_ARID1(0xf) | DTRC_ARID0(0xe));
  364. }
  365. static void vou_hw_init(struct zx_vou_hw *vou)
  366. {
  367. /* Set GL0 to main channel and GL1 to aux channel */
  368. zx_writel_mask(vou->osd + OSD_CTRL0, OSD_CTRL0_GL0_SEL, 0);
  369. zx_writel_mask(vou->osd + OSD_CTRL0, OSD_CTRL0_GL1_SEL,
  370. OSD_CTRL0_GL1_SEL);
  371. /* Release reset for all VOU modules */
  372. zx_writel(vou->vouctl + VOU_SOFT_RST, ~0);
  373. /* Select main clock for GL0 and aux clock for GL1 module */
  374. zx_writel_mask(vou->vouctl + VOU_CLK_SEL, VOU_CLK_GL0_SEL, 0);
  375. zx_writel_mask(vou->vouctl + VOU_CLK_SEL, VOU_CLK_GL1_SEL,
  376. VOU_CLK_GL1_SEL);
  377. /* Enable clock auto-gating for all VOU modules */
  378. zx_writel(vou->vouctl + VOU_CLK_REQEN, ~0);
  379. /* Enable all VOU module clocks */
  380. zx_writel(vou->vouctl + VOU_CLK_EN, ~0);
  381. /* Clear both OSD and TIMING_CTRL interrupt state */
  382. zx_writel(vou->osd + OSD_INT_CLRSTA, ~0);
  383. zx_writel(vou->timing + TIMING_INT_STATE, ~0);
  384. /* Enable OSD and TIMING_CTRL interrrupts */
  385. zx_writel(vou->osd + OSD_INT_MSK, OSD_INT_ENABLE);
  386. zx_writel(vou->timing + TIMING_INT_CTRL, TIMING_INT_ENABLE);
  387. /* Select GPC as input to gl/vl scaler as a sane default setting */
  388. zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a);
  389. /*
  390. * Needs to reset channel and layer logic per frame when frame starts
  391. * to get VOU work properly.
  392. */
  393. zx_writel_mask(vou->osd + OSD_RST_CLR, RST_PER_FRAME, RST_PER_FRAME);
  394. vou_dtrc_init(vou);
  395. }
  396. static int zx_crtc_bind(struct device *dev, struct device *master, void *data)
  397. {
  398. struct platform_device *pdev = to_platform_device(dev);
  399. struct drm_device *drm = data;
  400. struct zx_vou_hw *vou;
  401. struct resource *res;
  402. int irq;
  403. int ret;
  404. vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL);
  405. if (!vou)
  406. return -ENOMEM;
  407. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "osd");
  408. vou->osd = devm_ioremap_resource(dev, res);
  409. if (IS_ERR(vou->osd)) {
  410. ret = PTR_ERR(vou->osd);
  411. DRM_DEV_ERROR(dev, "failed to remap osd region: %d\n", ret);
  412. return ret;
  413. }
  414. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "timing_ctrl");
  415. vou->timing = devm_ioremap_resource(dev, res);
  416. if (IS_ERR(vou->timing)) {
  417. ret = PTR_ERR(vou->timing);
  418. DRM_DEV_ERROR(dev, "failed to remap timing_ctrl region: %d\n",
  419. ret);
  420. return ret;
  421. }
  422. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dtrc");
  423. vou->dtrc = devm_ioremap_resource(dev, res);
  424. if (IS_ERR(vou->dtrc)) {
  425. ret = PTR_ERR(vou->dtrc);
  426. DRM_DEV_ERROR(dev, "failed to remap dtrc region: %d\n", ret);
  427. return ret;
  428. }
  429. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vou_ctrl");
  430. vou->vouctl = devm_ioremap_resource(dev, res);
  431. if (IS_ERR(vou->vouctl)) {
  432. ret = PTR_ERR(vou->vouctl);
  433. DRM_DEV_ERROR(dev, "failed to remap vou_ctrl region: %d\n",
  434. ret);
  435. return ret;
  436. }
  437. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otfppu");
  438. vou->otfppu = devm_ioremap_resource(dev, res);
  439. if (IS_ERR(vou->otfppu)) {
  440. ret = PTR_ERR(vou->otfppu);
  441. DRM_DEV_ERROR(dev, "failed to remap otfppu region: %d\n", ret);
  442. return ret;
  443. }
  444. irq = platform_get_irq(pdev, 0);
  445. if (irq < 0)
  446. return irq;
  447. vou->axi_clk = devm_clk_get(dev, "aclk");
  448. if (IS_ERR(vou->axi_clk)) {
  449. ret = PTR_ERR(vou->axi_clk);
  450. DRM_DEV_ERROR(dev, "failed to get axi_clk: %d\n", ret);
  451. return ret;
  452. }
  453. vou->ppu_clk = devm_clk_get(dev, "ppu_wclk");
  454. if (IS_ERR(vou->ppu_clk)) {
  455. ret = PTR_ERR(vou->ppu_clk);
  456. DRM_DEV_ERROR(dev, "failed to get ppu_clk: %d\n", ret);
  457. return ret;
  458. }
  459. ret = clk_prepare_enable(vou->axi_clk);
  460. if (ret) {
  461. DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret);
  462. return ret;
  463. }
  464. clk_prepare_enable(vou->ppu_clk);
  465. if (ret) {
  466. DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret);
  467. goto disable_axi_clk;
  468. }
  469. vou->dev = dev;
  470. dev_set_drvdata(dev, vou);
  471. vou_hw_init(vou);
  472. ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou);
  473. if (ret < 0) {
  474. DRM_DEV_ERROR(dev, "failed to request vou irq: %d\n", ret);
  475. goto disable_ppu_clk;
  476. }
  477. ret = zx_crtc_init(drm, vou, VOU_CHN_MAIN);
  478. if (ret) {
  479. DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n",
  480. ret);
  481. goto disable_ppu_clk;
  482. }
  483. ret = zx_crtc_init(drm, vou, VOU_CHN_AUX);
  484. if (ret) {
  485. DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n",
  486. ret);
  487. goto disable_ppu_clk;
  488. }
  489. return 0;
  490. disable_ppu_clk:
  491. clk_disable_unprepare(vou->ppu_clk);
  492. disable_axi_clk:
  493. clk_disable_unprepare(vou->axi_clk);
  494. return ret;
  495. }
  496. static void zx_crtc_unbind(struct device *dev, struct device *master,
  497. void *data)
  498. {
  499. struct zx_vou_hw *vou = dev_get_drvdata(dev);
  500. clk_disable_unprepare(vou->axi_clk);
  501. clk_disable_unprepare(vou->ppu_clk);
  502. }
  503. static const struct component_ops zx_crtc_component_ops = {
  504. .bind = zx_crtc_bind,
  505. .unbind = zx_crtc_unbind,
  506. };
  507. static int zx_crtc_probe(struct platform_device *pdev)
  508. {
  509. return component_add(&pdev->dev, &zx_crtc_component_ops);
  510. }
  511. static int zx_crtc_remove(struct platform_device *pdev)
  512. {
  513. component_del(&pdev->dev, &zx_crtc_component_ops);
  514. return 0;
  515. }
  516. static const struct of_device_id zx_crtc_of_match[] = {
  517. { .compatible = "zte,zx296718-dpc", },
  518. { /* end */ },
  519. };
  520. MODULE_DEVICE_TABLE(of, zx_crtc_of_match);
  521. struct platform_driver zx_crtc_driver = {
  522. .probe = zx_crtc_probe,
  523. .remove = zx_crtc_remove,
  524. .driver = {
  525. .name = "zx-crtc",
  526. .of_match_table = zx_crtc_of_match,
  527. },
  528. };