1 /* 2 * Copyright (C) STMicroelectronics SA 2014 3 * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> 4 * Vincent Abriou <vincent.abriou@st.com> 5 * for STMicroelectronics. 6 * License terms: GNU General Public License (GPL), version 2 7 */ 8 9 #include <linux/clk.h> 10 #include <linux/component.h> 11 #include <linux/module.h> 12 #include <linux/of_platform.h> 13 #include <linux/platform_device.h> 14 #include <linux/reset.h> 15 #include <linux/seq_file.h> 16 17 #include <drm/drmP.h> 18 #include <drm/drm_crtc_helper.h> 19 20 #include "sti_crtc.h" 21 #include "sti_drv.h" 22 #include "sti_vtg.h" 23 24 /* glue registers */ 25 #define TVO_CSC_MAIN_M0 0x000 26 #define TVO_CSC_MAIN_M1 0x004 27 #define TVO_CSC_MAIN_M2 0x008 28 #define TVO_CSC_MAIN_M3 0x00c 29 #define TVO_CSC_MAIN_M4 0x010 30 #define TVO_CSC_MAIN_M5 0x014 31 #define TVO_CSC_MAIN_M6 0x018 32 #define TVO_CSC_MAIN_M7 0x01c 33 #define TVO_MAIN_IN_VID_FORMAT 0x030 34 #define TVO_CSC_AUX_M0 0x100 35 #define TVO_CSC_AUX_M1 0x104 36 #define TVO_CSC_AUX_M2 0x108 37 #define TVO_CSC_AUX_M3 0x10c 38 #define TVO_CSC_AUX_M4 0x110 39 #define TVO_CSC_AUX_M5 0x114 40 #define TVO_CSC_AUX_M6 0x118 41 #define TVO_CSC_AUX_M7 0x11c 42 #define TVO_AUX_IN_VID_FORMAT 0x130 43 #define TVO_VIP_HDF 0x400 44 #define TVO_HD_SYNC_SEL 0x418 45 #define TVO_HD_DAC_CFG_OFF 0x420 46 #define TVO_VIP_HDMI 0x500 47 #define TVO_HDMI_FORCE_COLOR_0 0x504 48 #define TVO_HDMI_FORCE_COLOR_1 0x508 49 #define TVO_HDMI_CLIP_VALUE_B_CB 0x50c 50 #define TVO_HDMI_CLIP_VALUE_Y_G 0x510 51 #define TVO_HDMI_CLIP_VALUE_R_CR 0x514 52 #define TVO_HDMI_SYNC_SEL 0x518 53 #define TVO_HDMI_DFV_OBS 0x540 54 #define TVO_VIP_DVO 0x600 55 #define TVO_DVO_SYNC_SEL 0x618 56 #define TVO_DVO_CONFIG 0x620 57 58 #define TVO_IN_FMT_SIGNED BIT(0) 59 #define TVO_SYNC_EXT BIT(4) 60 61 #define TVO_VIP_REORDER_R_SHIFT 24 62 #define TVO_VIP_REORDER_G_SHIFT 20 63 #define TVO_VIP_REORDER_B_SHIFT 16 64 #define TVO_VIP_REORDER_MASK 0x3 65 #define TVO_VIP_REORDER_Y_G_SEL 0 66 #define TVO_VIP_REORDER_CB_B_SEL 1 67 #define TVO_VIP_REORDER_CR_R_SEL 2 68 69 #define TVO_VIP_CLIP_SHIFT 8 70 #define TVO_VIP_CLIP_MASK 0x7 71 #define TVO_VIP_CLIP_DISABLED 0 72 #define TVO_VIP_CLIP_EAV_SAV 1 73 #define TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y 2 74 #define TVO_VIP_CLIP_LIMITED_RANGE_CB_CR 3 75 #define TVO_VIP_CLIP_PROG_RANGE 4 76 77 #define TVO_VIP_RND_SHIFT 4 78 #define TVO_VIP_RND_MASK 0x3 79 #define TVO_VIP_RND_8BIT_ROUNDED 0 80 #define TVO_VIP_RND_10BIT_ROUNDED 1 81 #define TVO_VIP_RND_12BIT_ROUNDED 2 82 83 #define TVO_VIP_SEL_INPUT_MASK 0xf 84 #define TVO_VIP_SEL_INPUT_MAIN 0x0 85 #define TVO_VIP_SEL_INPUT_AUX 0x8 86 #define TVO_VIP_SEL_INPUT_FORCE_COLOR 0xf 87 #define TVO_VIP_SEL_INPUT_BYPASS_MASK 0x1 88 #define TVO_VIP_SEL_INPUT_BYPASSED 1 89 90 #define TVO_SYNC_MAIN_VTG_SET_REF 0x00 91 #define TVO_SYNC_AUX_VTG_SET_REF 0x10 92 93 #define TVO_SYNC_HD_DCS_SHIFT 8 94 95 #define TVO_SYNC_DVO_PAD_HSYNC_SHIFT 8 96 #define TVO_SYNC_DVO_PAD_VSYNC_SHIFT 16 97 98 #define ENCODER_CRTC_MASK (BIT(0) | BIT(1)) 99 100 #define TVO_MIN_HD_HEIGHT 720 101 102 /* enum listing the supported output data format */ 103 enum sti_tvout_video_out_type { 104 STI_TVOUT_VIDEO_OUT_RGB, 105 STI_TVOUT_VIDEO_OUT_YUV, 106 }; 107 108 struct sti_tvout { 109 struct device *dev; 110 struct drm_device *drm_dev; 111 void __iomem *regs; 112 struct reset_control *reset; 113 struct drm_encoder *hdmi; 114 struct drm_encoder *hda; 115 struct drm_encoder *dvo; 116 bool debugfs_registered; 117 }; 118 119 struct sti_tvout_encoder { 120 struct drm_encoder encoder; 121 struct sti_tvout *tvout; 122 }; 123 124 #define to_sti_tvout_encoder(x) \ 125 container_of(x, struct sti_tvout_encoder, encoder) 126 127 #define to_sti_tvout(x) to_sti_tvout_encoder(x)->tvout 128 129 /* preformatter conversion matrix */ 130 static const u32 rgb_to_ycbcr_601[8] = { 131 0xF927082E, 0x04C9FEAB, 0x01D30964, 0xFA95FD3D, 132 0x0000082E, 0x00002000, 0x00002000, 0x00000000 133 }; 134 135 /* 709 RGB to YCbCr */ 136 static const u32 rgb_to_ycbcr_709[8] = { 137 0xF891082F, 0x0367FF40, 0x01280B71, 0xF9B1FE20, 138 0x0000082F, 0x00002000, 0x00002000, 0x00000000 139 }; 140 141 static u32 tvout_read(struct sti_tvout *tvout, int offset) 142 { 143 return readl(tvout->regs + offset); 144 } 145 146 static void tvout_write(struct sti_tvout *tvout, u32 val, int offset) 147 { 148 writel(val, tvout->regs + offset); 149 } 150 151 /** 152 * Set the clipping mode of a VIP 153 * 154 * @tvout: tvout structure 155 * @reg: register to set 156 * @cr_r: 157 * @y_g: 158 * @cb_b: 159 */ 160 static void tvout_vip_set_color_order(struct sti_tvout *tvout, int reg, 161 u32 cr_r, u32 y_g, u32 cb_b) 162 { 163 u32 val = tvout_read(tvout, reg); 164 165 val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT); 166 val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT); 167 val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_B_SHIFT); 168 val |= cr_r << TVO_VIP_REORDER_R_SHIFT; 169 val |= y_g << TVO_VIP_REORDER_G_SHIFT; 170 val |= cb_b << TVO_VIP_REORDER_B_SHIFT; 171 172 tvout_write(tvout, val, reg); 173 } 174 175 /** 176 * Set the clipping mode of a VIP 177 * 178 * @tvout: tvout structure 179 * @reg: register to set 180 * @range: clipping range 181 */ 182 static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, int reg, u32 range) 183 { 184 u32 val = tvout_read(tvout, reg); 185 186 val &= ~(TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT); 187 val |= range << TVO_VIP_CLIP_SHIFT; 188 tvout_write(tvout, val, reg); 189 } 190 191 /** 192 * Set the rounded value of a VIP 193 * 194 * @tvout: tvout structure 195 * @reg: register to set 196 * @rnd: rounded val per component 197 */ 198 static void tvout_vip_set_rnd(struct sti_tvout *tvout, int reg, u32 rnd) 199 { 200 u32 val = tvout_read(tvout, reg); 201 202 val &= ~(TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT); 203 val |= rnd << TVO_VIP_RND_SHIFT; 204 tvout_write(tvout, val, reg); 205 } 206 207 /** 208 * Select the VIP input 209 * 210 * @tvout: tvout structure 211 * @reg: register to set 212 * @main_path: main or auxiliary path 213 * @sel_input: selected_input (main/aux + conv) 214 */ 215 static void tvout_vip_set_sel_input(struct sti_tvout *tvout, 216 int reg, 217 bool main_path, 218 enum sti_tvout_video_out_type video_out) 219 { 220 u32 sel_input; 221 u32 val = tvout_read(tvout, reg); 222 223 if (main_path) 224 sel_input = TVO_VIP_SEL_INPUT_MAIN; 225 else 226 sel_input = TVO_VIP_SEL_INPUT_AUX; 227 228 switch (video_out) { 229 case STI_TVOUT_VIDEO_OUT_RGB: 230 sel_input |= TVO_VIP_SEL_INPUT_BYPASSED; 231 break; 232 case STI_TVOUT_VIDEO_OUT_YUV: 233 sel_input &= ~TVO_VIP_SEL_INPUT_BYPASSED; 234 break; 235 } 236 237 /* on stih407 chip the sel_input bypass mode logic is inverted */ 238 sel_input = sel_input ^ TVO_VIP_SEL_INPUT_BYPASS_MASK; 239 240 val &= ~TVO_VIP_SEL_INPUT_MASK; 241 val |= sel_input; 242 tvout_write(tvout, val, reg); 243 } 244 245 /** 246 * Select the input video signed or unsigned 247 * 248 * @tvout: tvout structure 249 * @reg: register to set 250 * @in_vid_signed: used video input format 251 */ 252 static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout, 253 int reg, u32 in_vid_fmt) 254 { 255 u32 val = tvout_read(tvout, reg); 256 257 val &= ~TVO_IN_FMT_SIGNED; 258 val |= in_vid_fmt; 259 tvout_write(tvout, val, reg); 260 } 261 262 /** 263 * Set preformatter matrix 264 * 265 * @tvout: tvout structure 266 * @mode: display mode structure 267 */ 268 static void tvout_preformatter_set_matrix(struct sti_tvout *tvout, 269 struct drm_display_mode *mode) 270 { 271 unsigned int i; 272 const u32 *pf_matrix; 273 274 if (mode->vdisplay >= TVO_MIN_HD_HEIGHT) 275 pf_matrix = rgb_to_ycbcr_709; 276 else 277 pf_matrix = rgb_to_ycbcr_601; 278 279 for (i = 0; i < 8; i++) { 280 tvout_write(tvout, *(pf_matrix + i), 281 TVO_CSC_MAIN_M0 + (i * 4)); 282 tvout_write(tvout, *(pf_matrix + i), 283 TVO_CSC_AUX_M0 + (i * 4)); 284 } 285 } 286 287 /** 288 * Start VIP block for DVO output 289 * 290 * @tvout: pointer on tvout structure 291 * @main_path: true if main path has to be used in the vip configuration 292 * else aux path is used. 293 */ 294 static void tvout_dvo_start(struct sti_tvout *tvout, bool main_path) 295 { 296 u32 tvo_in_vid_format; 297 int val, tmp; 298 299 dev_dbg(tvout->dev, "%s\n", __func__); 300 301 if (main_path) { 302 DRM_DEBUG_DRIVER("main vip for DVO\n"); 303 /* Select the input sync for dvo */ 304 tmp = TVO_SYNC_MAIN_VTG_SET_REF | VTG_SYNC_ID_DVO; 305 val = tmp << TVO_SYNC_DVO_PAD_VSYNC_SHIFT; 306 val |= tmp << TVO_SYNC_DVO_PAD_HSYNC_SHIFT; 307 val |= tmp; 308 tvout_write(tvout, val, TVO_DVO_SYNC_SEL); 309 tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT; 310 } else { 311 DRM_DEBUG_DRIVER("aux vip for DVO\n"); 312 /* Select the input sync for dvo */ 313 tmp = TVO_SYNC_AUX_VTG_SET_REF | VTG_SYNC_ID_DVO; 314 val = tmp << TVO_SYNC_DVO_PAD_VSYNC_SHIFT; 315 val |= tmp << TVO_SYNC_DVO_PAD_HSYNC_SHIFT; 316 val |= tmp; 317 tvout_write(tvout, val, TVO_DVO_SYNC_SEL); 318 tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT; 319 } 320 321 /* Set color channel order */ 322 tvout_vip_set_color_order(tvout, TVO_VIP_DVO, 323 TVO_VIP_REORDER_CR_R_SEL, 324 TVO_VIP_REORDER_Y_G_SEL, 325 TVO_VIP_REORDER_CB_B_SEL); 326 327 /* Set clipping mode */ 328 tvout_vip_set_clip_mode(tvout, TVO_VIP_DVO, TVO_VIP_CLIP_DISABLED); 329 330 /* Set round mode (rounded to 8-bit per component) */ 331 tvout_vip_set_rnd(tvout, TVO_VIP_DVO, TVO_VIP_RND_8BIT_ROUNDED); 332 333 /* Set input video format */ 334 tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format, TVO_IN_FMT_SIGNED); 335 336 /* Input selection */ 337 tvout_vip_set_sel_input(tvout, TVO_VIP_DVO, main_path, 338 STI_TVOUT_VIDEO_OUT_RGB); 339 } 340 341 /** 342 * Start VIP block for HDMI output 343 * 344 * @tvout: pointer on tvout structure 345 * @main_path: true if main path has to be used in the vip configuration 346 * else aux path is used. 347 */ 348 static void tvout_hdmi_start(struct sti_tvout *tvout, bool main_path) 349 { 350 u32 tvo_in_vid_format; 351 352 dev_dbg(tvout->dev, "%s\n", __func__); 353 354 if (main_path) { 355 DRM_DEBUG_DRIVER("main vip for hdmi\n"); 356 /* select the input sync for hdmi */ 357 tvout_write(tvout, 358 TVO_SYNC_MAIN_VTG_SET_REF | VTG_SYNC_ID_HDMI, 359 TVO_HDMI_SYNC_SEL); 360 tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT; 361 } else { 362 DRM_DEBUG_DRIVER("aux vip for hdmi\n"); 363 /* select the input sync for hdmi */ 364 tvout_write(tvout, 365 TVO_SYNC_AUX_VTG_SET_REF | VTG_SYNC_ID_HDMI, 366 TVO_HDMI_SYNC_SEL); 367 tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT; 368 } 369 370 /* set color channel order */ 371 tvout_vip_set_color_order(tvout, TVO_VIP_HDMI, 372 TVO_VIP_REORDER_CR_R_SEL, 373 TVO_VIP_REORDER_Y_G_SEL, 374 TVO_VIP_REORDER_CB_B_SEL); 375 376 /* set clipping mode */ 377 tvout_vip_set_clip_mode(tvout, TVO_VIP_HDMI, TVO_VIP_CLIP_DISABLED); 378 379 /* set round mode (rounded to 8-bit per component) */ 380 tvout_vip_set_rnd(tvout, TVO_VIP_HDMI, TVO_VIP_RND_8BIT_ROUNDED); 381 382 /* set input video format */ 383 tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format, TVO_IN_FMT_SIGNED); 384 385 /* input selection */ 386 tvout_vip_set_sel_input(tvout, TVO_VIP_HDMI, main_path, 387 STI_TVOUT_VIDEO_OUT_RGB); 388 } 389 390 /** 391 * Start HDF VIP and HD DAC 392 * 393 * @tvout: pointer on tvout structure 394 * @main_path: true if main path has to be used in the vip configuration 395 * else aux path is used. 396 */ 397 static void tvout_hda_start(struct sti_tvout *tvout, bool main_path) 398 { 399 u32 tvo_in_vid_format; 400 int val; 401 402 dev_dbg(tvout->dev, "%s\n", __func__); 403 404 if (main_path) { 405 DRM_DEBUG_DRIVER("main vip for HDF\n"); 406 /* Select the input sync for HD analog and HD DCS */ 407 val = TVO_SYNC_MAIN_VTG_SET_REF | VTG_SYNC_ID_HDDCS; 408 val = val << TVO_SYNC_HD_DCS_SHIFT; 409 val |= TVO_SYNC_MAIN_VTG_SET_REF | VTG_SYNC_ID_HDF; 410 tvout_write(tvout, val, TVO_HD_SYNC_SEL); 411 tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT; 412 } else { 413 DRM_DEBUG_DRIVER("aux vip for HDF\n"); 414 /* Select the input sync for HD analog and HD DCS */ 415 val = TVO_SYNC_AUX_VTG_SET_REF | VTG_SYNC_ID_HDDCS; 416 val = val << TVO_SYNC_HD_DCS_SHIFT; 417 val |= TVO_SYNC_AUX_VTG_SET_REF | VTG_SYNC_ID_HDF; 418 tvout_write(tvout, val, TVO_HD_SYNC_SEL); 419 tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT; 420 } 421 422 /* set color channel order */ 423 tvout_vip_set_color_order(tvout, TVO_VIP_HDF, 424 TVO_VIP_REORDER_CR_R_SEL, 425 TVO_VIP_REORDER_Y_G_SEL, 426 TVO_VIP_REORDER_CB_B_SEL); 427 428 /* set clipping mode */ 429 tvout_vip_set_clip_mode(tvout, TVO_VIP_HDF, TVO_VIP_CLIP_DISABLED); 430 431 /* set round mode (rounded to 10-bit per component) */ 432 tvout_vip_set_rnd(tvout, TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED); 433 434 /* Set input video format */ 435 tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format, TVO_IN_FMT_SIGNED); 436 437 /* Input selection */ 438 tvout_vip_set_sel_input(tvout, TVO_VIP_HDF, main_path, 439 STI_TVOUT_VIDEO_OUT_YUV); 440 441 /* power up HD DAC */ 442 tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF); 443 } 444 445 #define DBGFS_DUMP(reg) seq_printf(s, "\n %-25s 0x%08X", #reg, \ 446 readl(tvout->regs + reg)) 447 448 static void tvout_dbg_vip(struct seq_file *s, int val) 449 { 450 int r, g, b, tmp, mask; 451 char *const reorder[] = {"Y_G", "Cb_B", "Cr_R"}; 452 char *const clipping[] = {"No", "EAV/SAV", "Limited range RGB/Y", 453 "Limited range Cb/Cr", "decided by register"}; 454 char *const round[] = {"8-bit", "10-bit", "12-bit"}; 455 char *const input_sel[] = {"Main (color matrix enabled)", 456 "Main (color matrix by-passed)", 457 "", "", "", "", "", "", 458 "Aux (color matrix enabled)", 459 "Aux (color matrix by-passed)", 460 "", "", "", "", "", "Force value"}; 461 462 seq_puts(s, "\t"); 463 mask = TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT; 464 r = (val & mask) >> TVO_VIP_REORDER_R_SHIFT; 465 mask = TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT; 466 g = (val & mask) >> TVO_VIP_REORDER_G_SHIFT; 467 mask = TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_B_SHIFT; 468 b = (val & mask) >> TVO_VIP_REORDER_B_SHIFT; 469 seq_printf(s, "%-24s %s->%s %s->%s %s->%s\n", "Reorder:", 470 reorder[r], reorder[TVO_VIP_REORDER_CR_R_SEL], 471 reorder[g], reorder[TVO_VIP_REORDER_Y_G_SEL], 472 reorder[b], reorder[TVO_VIP_REORDER_CB_B_SEL]); 473 seq_puts(s, "\t\t\t\t\t"); 474 mask = TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT; 475 tmp = (val & mask) >> TVO_VIP_CLIP_SHIFT; 476 seq_printf(s, "%-24s %s\n", "Clipping:", clipping[tmp]); 477 seq_puts(s, "\t\t\t\t\t"); 478 mask = TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT; 479 tmp = (val & mask) >> TVO_VIP_RND_SHIFT; 480 seq_printf(s, "%-24s input data rounded to %s per component\n", 481 "Round:", round[tmp]); 482 seq_puts(s, "\t\t\t\t\t"); 483 tmp = (val & TVO_VIP_SEL_INPUT_MASK); 484 seq_printf(s, "%-24s %s", "Input selection:", input_sel[tmp]); 485 } 486 487 static void tvout_dbg_hd_dac_cfg(struct seq_file *s, int val) 488 { 489 seq_printf(s, "\t%-24s %s", "HD DAC:", 490 val & 1 ? "disabled" : "enabled"); 491 } 492 493 static int tvout_dbg_show(struct seq_file *s, void *data) 494 { 495 struct drm_info_node *node = s->private; 496 struct sti_tvout *tvout = (struct sti_tvout *)node->info_ent->data; 497 struct drm_crtc *crtc; 498 499 seq_printf(s, "TVOUT: (vaddr = 0x%p)", tvout->regs); 500 501 seq_puts(s, "\n\n HDMI encoder: "); 502 crtc = tvout->hdmi->crtc; 503 if (crtc) { 504 seq_printf(s, "connected to %s path", 505 sti_crtc_is_main(crtc) ? "main" : "aux"); 506 DBGFS_DUMP(TVO_HDMI_SYNC_SEL); 507 DBGFS_DUMP(TVO_VIP_HDMI); 508 tvout_dbg_vip(s, readl(tvout->regs + TVO_VIP_HDMI)); 509 } else { 510 seq_puts(s, "disabled"); 511 } 512 513 seq_puts(s, "\n\n DVO encoder: "); 514 crtc = tvout->dvo->crtc; 515 if (crtc) { 516 seq_printf(s, "connected to %s path", 517 sti_crtc_is_main(crtc) ? "main" : "aux"); 518 DBGFS_DUMP(TVO_DVO_SYNC_SEL); 519 DBGFS_DUMP(TVO_DVO_CONFIG); 520 DBGFS_DUMP(TVO_VIP_DVO); 521 tvout_dbg_vip(s, readl(tvout->regs + TVO_VIP_DVO)); 522 } else { 523 seq_puts(s, "disabled"); 524 } 525 526 seq_puts(s, "\n\n HDA encoder: "); 527 crtc = tvout->hda->crtc; 528 if (crtc) { 529 seq_printf(s, "connected to %s path", 530 sti_crtc_is_main(crtc) ? "main" : "aux"); 531 DBGFS_DUMP(TVO_HD_SYNC_SEL); 532 DBGFS_DUMP(TVO_HD_DAC_CFG_OFF); 533 tvout_dbg_hd_dac_cfg(s, 534 readl(tvout->regs + TVO_HD_DAC_CFG_OFF)); 535 DBGFS_DUMP(TVO_VIP_HDF); 536 tvout_dbg_vip(s, readl(tvout->regs + TVO_VIP_HDF)); 537 } else { 538 seq_puts(s, "disabled"); 539 } 540 541 seq_puts(s, "\n\n main path configuration"); 542 DBGFS_DUMP(TVO_CSC_MAIN_M0); 543 DBGFS_DUMP(TVO_CSC_MAIN_M1); 544 DBGFS_DUMP(TVO_CSC_MAIN_M2); 545 DBGFS_DUMP(TVO_CSC_MAIN_M3); 546 DBGFS_DUMP(TVO_CSC_MAIN_M4); 547 DBGFS_DUMP(TVO_CSC_MAIN_M5); 548 DBGFS_DUMP(TVO_CSC_MAIN_M6); 549 DBGFS_DUMP(TVO_CSC_MAIN_M7); 550 DBGFS_DUMP(TVO_MAIN_IN_VID_FORMAT); 551 552 seq_puts(s, "\n\n auxiliary path configuration"); 553 DBGFS_DUMP(TVO_CSC_AUX_M0); 554 DBGFS_DUMP(TVO_CSC_AUX_M2); 555 DBGFS_DUMP(TVO_CSC_AUX_M3); 556 DBGFS_DUMP(TVO_CSC_AUX_M4); 557 DBGFS_DUMP(TVO_CSC_AUX_M5); 558 DBGFS_DUMP(TVO_CSC_AUX_M6); 559 DBGFS_DUMP(TVO_CSC_AUX_M7); 560 DBGFS_DUMP(TVO_AUX_IN_VID_FORMAT); 561 seq_puts(s, "\n"); 562 563 return 0; 564 } 565 566 static struct drm_info_list tvout_debugfs_files[] = { 567 { "tvout", tvout_dbg_show, 0, NULL }, 568 }; 569 570 static void tvout_debugfs_exit(struct sti_tvout *tvout, struct drm_minor *minor) 571 { 572 drm_debugfs_remove_files(tvout_debugfs_files, 573 ARRAY_SIZE(tvout_debugfs_files), 574 minor); 575 } 576 577 static int tvout_debugfs_init(struct sti_tvout *tvout, struct drm_minor *minor) 578 { 579 unsigned int i; 580 581 for (i = 0; i < ARRAY_SIZE(tvout_debugfs_files); i++) 582 tvout_debugfs_files[i].data = tvout; 583 584 return drm_debugfs_create_files(tvout_debugfs_files, 585 ARRAY_SIZE(tvout_debugfs_files), 586 minor->debugfs_root, minor); 587 } 588 589 static void sti_tvout_encoder_dpms(struct drm_encoder *encoder, int mode) 590 { 591 } 592 593 static void sti_tvout_encoder_mode_set(struct drm_encoder *encoder, 594 struct drm_display_mode *mode, 595 struct drm_display_mode *adjusted_mode) 596 { 597 } 598 599 static void sti_tvout_encoder_destroy(struct drm_encoder *encoder) 600 { 601 struct sti_tvout_encoder *sti_encoder = to_sti_tvout_encoder(encoder); 602 603 drm_encoder_cleanup(encoder); 604 kfree(sti_encoder); 605 } 606 607 static int sti_tvout_late_register(struct drm_encoder *encoder) 608 { 609 struct sti_tvout *tvout = to_sti_tvout(encoder); 610 int ret; 611 612 if (tvout->debugfs_registered) 613 return 0; 614 615 ret = tvout_debugfs_init(tvout, encoder->dev->primary); 616 if (ret) 617 return ret; 618 619 tvout->debugfs_registered = true; 620 return 0; 621 } 622 623 static void sti_tvout_early_unregister(struct drm_encoder *encoder) 624 { 625 struct sti_tvout *tvout = to_sti_tvout(encoder); 626 627 if (!tvout->debugfs_registered) 628 return; 629 630 tvout_debugfs_exit(tvout, encoder->dev->primary); 631 tvout->debugfs_registered = false; 632 } 633 634 static const struct drm_encoder_funcs sti_tvout_encoder_funcs = { 635 .destroy = sti_tvout_encoder_destroy, 636 .late_register = sti_tvout_late_register, 637 .early_unregister = sti_tvout_early_unregister, 638 }; 639 640 static void sti_dvo_encoder_enable(struct drm_encoder *encoder) 641 { 642 struct sti_tvout *tvout = to_sti_tvout(encoder); 643 644 tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode); 645 646 tvout_dvo_start(tvout, sti_crtc_is_main(encoder->crtc)); 647 } 648 649 static void sti_dvo_encoder_disable(struct drm_encoder *encoder) 650 { 651 struct sti_tvout *tvout = to_sti_tvout(encoder); 652 653 /* Reset VIP register */ 654 tvout_write(tvout, 0x0, TVO_VIP_DVO); 655 } 656 657 static const struct drm_encoder_helper_funcs sti_dvo_encoder_helper_funcs = { 658 .dpms = sti_tvout_encoder_dpms, 659 .mode_set = sti_tvout_encoder_mode_set, 660 .enable = sti_dvo_encoder_enable, 661 .disable = sti_dvo_encoder_disable, 662 }; 663 664 static struct drm_encoder * 665 sti_tvout_create_dvo_encoder(struct drm_device *dev, 666 struct sti_tvout *tvout) 667 { 668 struct sti_tvout_encoder *encoder; 669 struct drm_encoder *drm_encoder; 670 671 encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL); 672 if (!encoder) 673 return NULL; 674 675 encoder->tvout = tvout; 676 677 drm_encoder = (struct drm_encoder *)encoder; 678 679 drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; 680 drm_encoder->possible_clones = 1 << 0; 681 682 drm_encoder_init(dev, drm_encoder, 683 &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_LVDS, 684 NULL); 685 686 drm_encoder_helper_add(drm_encoder, &sti_dvo_encoder_helper_funcs); 687 688 return drm_encoder; 689 } 690 691 static void sti_hda_encoder_enable(struct drm_encoder *encoder) 692 { 693 struct sti_tvout *tvout = to_sti_tvout(encoder); 694 695 tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode); 696 697 tvout_hda_start(tvout, sti_crtc_is_main(encoder->crtc)); 698 } 699 700 static void sti_hda_encoder_disable(struct drm_encoder *encoder) 701 { 702 struct sti_tvout *tvout = to_sti_tvout(encoder); 703 704 /* reset VIP register */ 705 tvout_write(tvout, 0x0, TVO_VIP_HDF); 706 707 /* power down HD DAC */ 708 tvout_write(tvout, 1, TVO_HD_DAC_CFG_OFF); 709 } 710 711 static const struct drm_encoder_helper_funcs sti_hda_encoder_helper_funcs = { 712 .dpms = sti_tvout_encoder_dpms, 713 .mode_set = sti_tvout_encoder_mode_set, 714 .commit = sti_hda_encoder_enable, 715 .disable = sti_hda_encoder_disable, 716 }; 717 718 static struct drm_encoder *sti_tvout_create_hda_encoder(struct drm_device *dev, 719 struct sti_tvout *tvout) 720 { 721 struct sti_tvout_encoder *encoder; 722 struct drm_encoder *drm_encoder; 723 724 encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL); 725 if (!encoder) 726 return NULL; 727 728 encoder->tvout = tvout; 729 730 drm_encoder = (struct drm_encoder *) encoder; 731 732 drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; 733 drm_encoder->possible_clones = 1 << 0; 734 735 drm_encoder_init(dev, drm_encoder, 736 &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_DAC, NULL); 737 738 drm_encoder_helper_add(drm_encoder, &sti_hda_encoder_helper_funcs); 739 740 return drm_encoder; 741 } 742 743 static void sti_hdmi_encoder_enable(struct drm_encoder *encoder) 744 { 745 struct sti_tvout *tvout = to_sti_tvout(encoder); 746 747 tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode); 748 749 tvout_hdmi_start(tvout, sti_crtc_is_main(encoder->crtc)); 750 } 751 752 static void sti_hdmi_encoder_disable(struct drm_encoder *encoder) 753 { 754 struct sti_tvout *tvout = to_sti_tvout(encoder); 755 756 /* reset VIP register */ 757 tvout_write(tvout, 0x0, TVO_VIP_HDMI); 758 } 759 760 static const struct drm_encoder_helper_funcs sti_hdmi_encoder_helper_funcs = { 761 .dpms = sti_tvout_encoder_dpms, 762 .mode_set = sti_tvout_encoder_mode_set, 763 .commit = sti_hdmi_encoder_enable, 764 .disable = sti_hdmi_encoder_disable, 765 }; 766 767 static struct drm_encoder *sti_tvout_create_hdmi_encoder(struct drm_device *dev, 768 struct sti_tvout *tvout) 769 { 770 struct sti_tvout_encoder *encoder; 771 struct drm_encoder *drm_encoder; 772 773 encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL); 774 if (!encoder) 775 return NULL; 776 777 encoder->tvout = tvout; 778 779 drm_encoder = (struct drm_encoder *) encoder; 780 781 drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; 782 drm_encoder->possible_clones = 1 << 1; 783 784 drm_encoder_init(dev, drm_encoder, 785 &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); 786 787 drm_encoder_helper_add(drm_encoder, &sti_hdmi_encoder_helper_funcs); 788 789 return drm_encoder; 790 } 791 792 static void sti_tvout_create_encoders(struct drm_device *dev, 793 struct sti_tvout *tvout) 794 { 795 tvout->hdmi = sti_tvout_create_hdmi_encoder(dev, tvout); 796 tvout->hda = sti_tvout_create_hda_encoder(dev, tvout); 797 tvout->dvo = sti_tvout_create_dvo_encoder(dev, tvout); 798 } 799 800 static void sti_tvout_destroy_encoders(struct sti_tvout *tvout) 801 { 802 if (tvout->hdmi) 803 drm_encoder_cleanup(tvout->hdmi); 804 tvout->hdmi = NULL; 805 806 if (tvout->hda) 807 drm_encoder_cleanup(tvout->hda); 808 tvout->hda = NULL; 809 810 if (tvout->dvo) 811 drm_encoder_cleanup(tvout->dvo); 812 tvout->dvo = NULL; 813 } 814 815 static int sti_tvout_bind(struct device *dev, struct device *master, void *data) 816 { 817 struct sti_tvout *tvout = dev_get_drvdata(dev); 818 struct drm_device *drm_dev = data; 819 820 tvout->drm_dev = drm_dev; 821 822 sti_tvout_create_encoders(drm_dev, tvout); 823 824 return 0; 825 } 826 827 static void sti_tvout_unbind(struct device *dev, struct device *master, 828 void *data) 829 { 830 struct sti_tvout *tvout = dev_get_drvdata(dev); 831 832 sti_tvout_destroy_encoders(tvout); 833 } 834 835 static const struct component_ops sti_tvout_ops = { 836 .bind = sti_tvout_bind, 837 .unbind = sti_tvout_unbind, 838 }; 839 840 static int sti_tvout_probe(struct platform_device *pdev) 841 { 842 struct device *dev = &pdev->dev; 843 struct device_node *node = dev->of_node; 844 struct sti_tvout *tvout; 845 struct resource *res; 846 847 DRM_INFO("%s\n", __func__); 848 849 if (!node) 850 return -ENODEV; 851 852 tvout = devm_kzalloc(dev, sizeof(*tvout), GFP_KERNEL); 853 if (!tvout) 854 return -ENOMEM; 855 856 tvout->dev = dev; 857 858 /* get Memory ressources */ 859 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tvout-reg"); 860 if (!res) { 861 DRM_ERROR("Invalid glue resource\n"); 862 return -ENOMEM; 863 } 864 tvout->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); 865 if (!tvout->regs) 866 return -ENOMEM; 867 868 /* get reset resources */ 869 tvout->reset = devm_reset_control_get(dev, "tvout"); 870 /* take tvout out of reset */ 871 if (!IS_ERR(tvout->reset)) 872 reset_control_deassert(tvout->reset); 873 874 platform_set_drvdata(pdev, tvout); 875 876 return component_add(dev, &sti_tvout_ops); 877 } 878 879 static int sti_tvout_remove(struct platform_device *pdev) 880 { 881 component_del(&pdev->dev, &sti_tvout_ops); 882 return 0; 883 } 884 885 static const struct of_device_id tvout_of_match[] = { 886 { .compatible = "st,stih407-tvout", }, 887 { /* end node */ } 888 }; 889 MODULE_DEVICE_TABLE(of, tvout_of_match); 890 891 struct platform_driver sti_tvout_driver = { 892 .driver = { 893 .name = "sti-tvout", 894 .owner = THIS_MODULE, 895 .of_match_table = tvout_of_match, 896 }, 897 .probe = sti_tvout_probe, 898 .remove = sti_tvout_remove, 899 }; 900 901 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 902 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 903 MODULE_LICENSE("GPL"); 904