1 /* 2 * Copyright (C) STMicroelectronics SA 2014 3 * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> 4 * Fabien Dessenne <fabien.dessenne@st.com> 5 * Vincent Abriou <vincent.abriou@st.com> 6 * for STMicroelectronics. 7 * License terms: GNU General Public License (GPL), version 2 8 */ 9 10 #include <linux/module.h> 11 #include <linux/notifier.h> 12 #include <linux/platform_device.h> 13 14 #include <drm/drmP.h> 15 16 #include "sti_vtg.h" 17 18 #define VTG_TYPE_MASTER 0 19 #define VTG_TYPE_SLAVE_BY_EXT0 1 20 21 /* registers offset */ 22 #define VTG_MODE 0x0000 23 #define VTG_CLKLN 0x0008 24 #define VTG_HLFLN 0x000C 25 #define VTG_DRST_AUTOC 0x0010 26 #define VTG_VID_TFO 0x0040 27 #define VTG_VID_TFS 0x0044 28 #define VTG_VID_BFO 0x0048 29 #define VTG_VID_BFS 0x004C 30 31 #define VTG_HOST_ITS 0x0078 32 #define VTG_HOST_ITS_BCLR 0x007C 33 #define VTG_HOST_ITM_BCLR 0x0088 34 #define VTG_HOST_ITM_BSET 0x008C 35 36 #define VTG_H_HD_1 0x00C0 37 #define VTG_TOP_V_VD_1 0x00C4 38 #define VTG_BOT_V_VD_1 0x00C8 39 #define VTG_TOP_V_HD_1 0x00CC 40 #define VTG_BOT_V_HD_1 0x00D0 41 42 #define VTG_H_HD_2 0x00E0 43 #define VTG_TOP_V_VD_2 0x00E4 44 #define VTG_BOT_V_VD_2 0x00E8 45 #define VTG_TOP_V_HD_2 0x00EC 46 #define VTG_BOT_V_HD_2 0x00F0 47 48 #define VTG_H_HD_3 0x0100 49 #define VTG_TOP_V_VD_3 0x0104 50 #define VTG_BOT_V_VD_3 0x0108 51 #define VTG_TOP_V_HD_3 0x010C 52 #define VTG_BOT_V_HD_3 0x0110 53 54 #define VTG_H_HD_4 0x0120 55 #define VTG_TOP_V_VD_4 0x0124 56 #define VTG_BOT_V_VD_4 0x0128 57 #define VTG_TOP_V_HD_4 0x012c 58 #define VTG_BOT_V_HD_4 0x0130 59 60 #define VTG_IRQ_BOTTOM BIT(0) 61 #define VTG_IRQ_TOP BIT(1) 62 #define VTG_IRQ_MASK (VTG_IRQ_TOP | VTG_IRQ_BOTTOM) 63 64 /* Delay introduced by the HDMI in nb of pixel */ 65 #define HDMI_DELAY (5) 66 67 /* delay introduced by the Arbitrary Waveform Generator in nb of pixels */ 68 #define AWG_DELAY_HD (-9) 69 #define AWG_DELAY_ED (-8) 70 #define AWG_DELAY_SD (-7) 71 72 LIST_HEAD(vtg_lookup); 73 74 /** 75 * STI VTG structure 76 * 77 * @dev: pointer to device driver 78 * @data: data associated to the device 79 * @irq: VTG irq 80 * @type: VTG type (main or aux) 81 * @notifier_list: notifier callback 82 * @crtc_id: the crtc id for vblank event 83 * @slave: slave vtg 84 * @link: List node to link the structure in lookup list 85 */ 86 struct sti_vtg { 87 struct device *dev; 88 struct device_node *np; 89 void __iomem *regs; 90 int irq; 91 u32 irq_status; 92 struct raw_notifier_head notifier_list; 93 int crtc_id; 94 struct sti_vtg *slave; 95 struct list_head link; 96 }; 97 98 static void vtg_register(struct sti_vtg *vtg) 99 { 100 list_add_tail(&vtg->link, &vtg_lookup); 101 } 102 103 struct sti_vtg *of_vtg_find(struct device_node *np) 104 { 105 struct sti_vtg *vtg; 106 107 list_for_each_entry(vtg, &vtg_lookup, link) { 108 if (vtg->np == np) 109 return vtg; 110 } 111 return NULL; 112 } 113 EXPORT_SYMBOL(of_vtg_find); 114 115 static void vtg_reset(struct sti_vtg *vtg) 116 { 117 /* reset slave and then master */ 118 if (vtg->slave) 119 vtg_reset(vtg->slave); 120 121 writel(1, vtg->regs + VTG_DRST_AUTOC); 122 } 123 124 static void vtg_set_output_window(void __iomem *regs, 125 const struct drm_display_mode *mode) 126 { 127 u32 video_top_field_start; 128 u32 video_top_field_stop; 129 u32 video_bottom_field_start; 130 u32 video_bottom_field_stop; 131 u32 xstart = sti_vtg_get_pixel_number(*mode, 0); 132 u32 ystart = sti_vtg_get_line_number(*mode, 0); 133 u32 xstop = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1); 134 u32 ystop = sti_vtg_get_line_number(*mode, mode->vdisplay - 1); 135 136 /* Set output window to fit the display mode selected */ 137 video_top_field_start = (ystart << 16) | xstart; 138 video_top_field_stop = (ystop << 16) | xstop; 139 140 /* Only progressive supported for now */ 141 video_bottom_field_start = video_top_field_start; 142 video_bottom_field_stop = video_top_field_stop; 143 144 writel(video_top_field_start, regs + VTG_VID_TFO); 145 writel(video_top_field_stop, regs + VTG_VID_TFS); 146 writel(video_bottom_field_start, regs + VTG_VID_BFO); 147 writel(video_bottom_field_stop, regs + VTG_VID_BFS); 148 } 149 150 static void vtg_set_mode(struct sti_vtg *vtg, 151 int type, const struct drm_display_mode *mode) 152 { 153 u32 tmp; 154 155 if (vtg->slave) 156 vtg_set_mode(vtg->slave, VTG_TYPE_SLAVE_BY_EXT0, mode); 157 158 /* Set the number of clock cycles per line */ 159 writel(mode->htotal, vtg->regs + VTG_CLKLN); 160 161 /* Set Half Line Per Field (only progressive supported for now) */ 162 writel(mode->vtotal * 2, vtg->regs + VTG_HLFLN); 163 164 /* Program output window */ 165 vtg_set_output_window(vtg->regs, mode); 166 167 /* prepare VTG set 1 for HDMI */ 168 tmp = (mode->hsync_end - mode->hsync_start + HDMI_DELAY) << 16; 169 tmp |= HDMI_DELAY; 170 writel(tmp, vtg->regs + VTG_H_HD_1); 171 172 tmp = (mode->vsync_end - mode->vsync_start + 1) << 16; 173 tmp |= 1; 174 writel(tmp, vtg->regs + VTG_TOP_V_VD_1); 175 writel(tmp, vtg->regs + VTG_BOT_V_VD_1); 176 177 tmp = HDMI_DELAY << 16; 178 tmp |= HDMI_DELAY; 179 writel(tmp, vtg->regs + VTG_TOP_V_HD_1); 180 writel(tmp, vtg->regs + VTG_BOT_V_HD_1); 181 182 /* prepare VTG set 2 for for HD DCS */ 183 tmp = (mode->hsync_end - mode->hsync_start) << 16; 184 writel(tmp, vtg->regs + VTG_H_HD_2); 185 186 tmp = (mode->vsync_end - mode->vsync_start + 1) << 16; 187 tmp |= 1; 188 writel(tmp, vtg->regs + VTG_TOP_V_VD_2); 189 writel(tmp, vtg->regs + VTG_BOT_V_VD_2); 190 writel(0, vtg->regs + VTG_TOP_V_HD_2); 191 writel(0, vtg->regs + VTG_BOT_V_HD_2); 192 193 /* prepare VTG set 3 for HD Analog in HD mode */ 194 tmp = (mode->hsync_end - mode->hsync_start + AWG_DELAY_HD) << 16; 195 tmp |= mode->htotal + AWG_DELAY_HD; 196 writel(tmp, vtg->regs + VTG_H_HD_3); 197 198 tmp = (mode->vsync_end - mode->vsync_start) << 16; 199 tmp |= mode->vtotal; 200 writel(tmp, vtg->regs + VTG_TOP_V_VD_3); 201 writel(tmp, vtg->regs + VTG_BOT_V_VD_3); 202 203 tmp = (mode->htotal + AWG_DELAY_HD) << 16; 204 tmp |= mode->htotal + AWG_DELAY_HD; 205 writel(tmp, vtg->regs + VTG_TOP_V_HD_3); 206 writel(tmp, vtg->regs + VTG_BOT_V_HD_3); 207 208 /* Prepare VTG set 4 for DVO */ 209 tmp = (mode->hsync_end - mode->hsync_start) << 16; 210 writel(tmp, vtg->regs + VTG_H_HD_4); 211 212 tmp = (mode->vsync_end - mode->vsync_start + 1) << 16; 213 tmp |= 1; 214 writel(tmp, vtg->regs + VTG_TOP_V_VD_4); 215 writel(tmp, vtg->regs + VTG_BOT_V_VD_4); 216 writel(0, vtg->regs + VTG_TOP_V_HD_4); 217 writel(0, vtg->regs + VTG_BOT_V_HD_4); 218 219 /* mode */ 220 writel(type, vtg->regs + VTG_MODE); 221 } 222 223 static void vtg_enable_irq(struct sti_vtg *vtg) 224 { 225 /* clear interrupt status and mask */ 226 writel(0xFFFF, vtg->regs + VTG_HOST_ITS_BCLR); 227 writel(0xFFFF, vtg->regs + VTG_HOST_ITM_BCLR); 228 writel(VTG_IRQ_MASK, vtg->regs + VTG_HOST_ITM_BSET); 229 } 230 231 void sti_vtg_set_config(struct sti_vtg *vtg, 232 const struct drm_display_mode *mode) 233 { 234 /* write configuration */ 235 vtg_set_mode(vtg, VTG_TYPE_MASTER, mode); 236 237 vtg_reset(vtg); 238 239 /* enable irq for the vtg vblank synchro */ 240 if (vtg->slave) 241 vtg_enable_irq(vtg->slave); 242 else 243 vtg_enable_irq(vtg); 244 } 245 EXPORT_SYMBOL(sti_vtg_set_config); 246 247 /** 248 * sti_vtg_get_line_number 249 * 250 * @mode: display mode to be used 251 * @y: line 252 * 253 * Return the line number according to the display mode taking 254 * into account the Sync and Back Porch information. 255 * Video frame line numbers start at 1, y starts at 0. 256 * In interlaced modes the start line is the field line number of the odd 257 * field, but y is still defined as a progressive frame. 258 */ 259 u32 sti_vtg_get_line_number(struct drm_display_mode mode, int y) 260 { 261 u32 start_line = mode.vtotal - mode.vsync_start + 1; 262 263 if (mode.flags & DRM_MODE_FLAG_INTERLACE) 264 start_line *= 2; 265 266 return start_line + y; 267 } 268 EXPORT_SYMBOL(sti_vtg_get_line_number); 269 270 /** 271 * sti_vtg_get_pixel_number 272 * 273 * @mode: display mode to be used 274 * @x: row 275 * 276 * Return the pixel number according to the display mode taking 277 * into account the Sync and Back Porch information. 278 * Pixels are counted from 0. 279 */ 280 u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x) 281 { 282 return mode.htotal - mode.hsync_start + x; 283 } 284 EXPORT_SYMBOL(sti_vtg_get_pixel_number); 285 286 int sti_vtg_register_client(struct sti_vtg *vtg, 287 struct notifier_block *nb, int crtc_id) 288 { 289 if (vtg->slave) 290 return sti_vtg_register_client(vtg->slave, nb, crtc_id); 291 292 vtg->crtc_id = crtc_id; 293 return raw_notifier_chain_register(&vtg->notifier_list, nb); 294 } 295 EXPORT_SYMBOL(sti_vtg_register_client); 296 297 int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb) 298 { 299 if (vtg->slave) 300 return sti_vtg_unregister_client(vtg->slave, nb); 301 302 return raw_notifier_chain_unregister(&vtg->notifier_list, nb); 303 } 304 EXPORT_SYMBOL(sti_vtg_unregister_client); 305 306 static irqreturn_t vtg_irq_thread(int irq, void *arg) 307 { 308 struct sti_vtg *vtg = arg; 309 u32 event; 310 311 event = (vtg->irq_status & VTG_IRQ_TOP) ? 312 VTG_TOP_FIELD_EVENT : VTG_BOTTOM_FIELD_EVENT; 313 314 raw_notifier_call_chain(&vtg->notifier_list, event, &vtg->crtc_id); 315 316 return IRQ_HANDLED; 317 } 318 319 static irqreturn_t vtg_irq(int irq, void *arg) 320 { 321 struct sti_vtg *vtg = arg; 322 323 vtg->irq_status = readl(vtg->regs + VTG_HOST_ITS); 324 325 writel(vtg->irq_status, vtg->regs + VTG_HOST_ITS_BCLR); 326 327 /* force sync bus write */ 328 readl(vtg->regs + VTG_HOST_ITS); 329 330 return IRQ_WAKE_THREAD; 331 } 332 333 static int vtg_probe(struct platform_device *pdev) 334 { 335 struct device *dev = &pdev->dev; 336 struct device_node *np; 337 struct sti_vtg *vtg; 338 struct resource *res; 339 int ret; 340 341 vtg = devm_kzalloc(dev, sizeof(*vtg), GFP_KERNEL); 342 if (!vtg) 343 return -ENOMEM; 344 345 vtg->dev = dev; 346 vtg->np = pdev->dev.of_node; 347 348 /* Get Memory ressources */ 349 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 350 if (!res) { 351 DRM_ERROR("Get memory resource failed\n"); 352 return -ENOMEM; 353 } 354 vtg->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); 355 356 np = of_parse_phandle(pdev->dev.of_node, "st,slave", 0); 357 if (np) { 358 vtg->slave = of_vtg_find(np); 359 360 if (!vtg->slave) 361 return -EPROBE_DEFER; 362 } else { 363 vtg->irq = platform_get_irq(pdev, 0); 364 if (IS_ERR_VALUE(vtg->irq)) { 365 DRM_ERROR("Failed to get VTG interrupt\n"); 366 return vtg->irq; 367 } 368 369 RAW_INIT_NOTIFIER_HEAD(&vtg->notifier_list); 370 371 ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq, 372 vtg_irq_thread, IRQF_ONESHOT, 373 dev_name(dev), vtg); 374 if (IS_ERR_VALUE(ret)) { 375 DRM_ERROR("Failed to register VTG interrupt\n"); 376 return ret; 377 } 378 } 379 380 vtg_register(vtg); 381 platform_set_drvdata(pdev, vtg); 382 383 DRM_INFO("%s %s\n", __func__, dev_name(vtg->dev)); 384 385 return 0; 386 } 387 388 static int vtg_remove(struct platform_device *pdev) 389 { 390 return 0; 391 } 392 393 static const struct of_device_id vtg_of_match[] = { 394 { .compatible = "st,vtg", }, 395 { /* sentinel */ } 396 }; 397 MODULE_DEVICE_TABLE(of, vtg_of_match); 398 399 struct platform_driver sti_vtg_driver = { 400 .driver = { 401 .name = "sti-vtg", 402 .owner = THIS_MODULE, 403 .of_match_table = vtg_of_match, 404 }, 405 .probe = vtg_probe, 406 .remove = vtg_remove, 407 }; 408 409 module_platform_driver(sti_vtg_driver); 410 411 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 412 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 413 MODULE_LICENSE("GPL"); 414