1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) STMicroelectronics SA 2014 4 * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> 5 * Vincent Abriou <vincent.abriou@st.com> 6 * for STMicroelectronics. 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_putc(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_putc(s, '\n'); 562 return 0; 563 } 564 565 static struct drm_info_list tvout_debugfs_files[] = { 566 { "tvout", tvout_dbg_show, 0, NULL }, 567 }; 568 569 static int tvout_debugfs_init(struct sti_tvout *tvout, struct drm_minor *minor) 570 { 571 unsigned int i; 572 573 for (i = 0; i < ARRAY_SIZE(tvout_debugfs_files); i++) 574 tvout_debugfs_files[i].data = tvout; 575 576 return drm_debugfs_create_files(tvout_debugfs_files, 577 ARRAY_SIZE(tvout_debugfs_files), 578 minor->debugfs_root, minor); 579 } 580 581 static void sti_tvout_encoder_dpms(struct drm_encoder *encoder, int mode) 582 { 583 } 584 585 static void sti_tvout_encoder_mode_set(struct drm_encoder *encoder, 586 struct drm_display_mode *mode, 587 struct drm_display_mode *adjusted_mode) 588 { 589 } 590 591 static void sti_tvout_encoder_destroy(struct drm_encoder *encoder) 592 { 593 struct sti_tvout_encoder *sti_encoder = to_sti_tvout_encoder(encoder); 594 595 drm_encoder_cleanup(encoder); 596 kfree(sti_encoder); 597 } 598 599 static int sti_tvout_late_register(struct drm_encoder *encoder) 600 { 601 struct sti_tvout *tvout = to_sti_tvout(encoder); 602 int ret; 603 604 if (tvout->debugfs_registered) 605 return 0; 606 607 ret = tvout_debugfs_init(tvout, encoder->dev->primary); 608 if (ret) 609 return ret; 610 611 tvout->debugfs_registered = true; 612 return 0; 613 } 614 615 static void sti_tvout_early_unregister(struct drm_encoder *encoder) 616 { 617 struct sti_tvout *tvout = to_sti_tvout(encoder); 618 619 if (!tvout->debugfs_registered) 620 return; 621 622 tvout->debugfs_registered = false; 623 } 624 625 static const struct drm_encoder_funcs sti_tvout_encoder_funcs = { 626 .destroy = sti_tvout_encoder_destroy, 627 .late_register = sti_tvout_late_register, 628 .early_unregister = sti_tvout_early_unregister, 629 }; 630 631 static void sti_dvo_encoder_enable(struct drm_encoder *encoder) 632 { 633 struct sti_tvout *tvout = to_sti_tvout(encoder); 634 635 tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode); 636 637 tvout_dvo_start(tvout, sti_crtc_is_main(encoder->crtc)); 638 } 639 640 static void sti_dvo_encoder_disable(struct drm_encoder *encoder) 641 { 642 struct sti_tvout *tvout = to_sti_tvout(encoder); 643 644 /* Reset VIP register */ 645 tvout_write(tvout, 0x0, TVO_VIP_DVO); 646 } 647 648 static const struct drm_encoder_helper_funcs sti_dvo_encoder_helper_funcs = { 649 .dpms = sti_tvout_encoder_dpms, 650 .mode_set = sti_tvout_encoder_mode_set, 651 .enable = sti_dvo_encoder_enable, 652 .disable = sti_dvo_encoder_disable, 653 }; 654 655 static struct drm_encoder * 656 sti_tvout_create_dvo_encoder(struct drm_device *dev, 657 struct sti_tvout *tvout) 658 { 659 struct sti_tvout_encoder *encoder; 660 struct drm_encoder *drm_encoder; 661 662 encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL); 663 if (!encoder) 664 return NULL; 665 666 encoder->tvout = tvout; 667 668 drm_encoder = (struct drm_encoder *)encoder; 669 670 drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; 671 drm_encoder->possible_clones = 1 << 0; 672 673 drm_encoder_init(dev, drm_encoder, 674 &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_LVDS, 675 NULL); 676 677 drm_encoder_helper_add(drm_encoder, &sti_dvo_encoder_helper_funcs); 678 679 return drm_encoder; 680 } 681 682 static void sti_hda_encoder_enable(struct drm_encoder *encoder) 683 { 684 struct sti_tvout *tvout = to_sti_tvout(encoder); 685 686 tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode); 687 688 tvout_hda_start(tvout, sti_crtc_is_main(encoder->crtc)); 689 } 690 691 static void sti_hda_encoder_disable(struct drm_encoder *encoder) 692 { 693 struct sti_tvout *tvout = to_sti_tvout(encoder); 694 695 /* reset VIP register */ 696 tvout_write(tvout, 0x0, TVO_VIP_HDF); 697 698 /* power down HD DAC */ 699 tvout_write(tvout, 1, TVO_HD_DAC_CFG_OFF); 700 } 701 702 static const struct drm_encoder_helper_funcs sti_hda_encoder_helper_funcs = { 703 .dpms = sti_tvout_encoder_dpms, 704 .mode_set = sti_tvout_encoder_mode_set, 705 .commit = sti_hda_encoder_enable, 706 .disable = sti_hda_encoder_disable, 707 }; 708 709 static struct drm_encoder *sti_tvout_create_hda_encoder(struct drm_device *dev, 710 struct sti_tvout *tvout) 711 { 712 struct sti_tvout_encoder *encoder; 713 struct drm_encoder *drm_encoder; 714 715 encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL); 716 if (!encoder) 717 return NULL; 718 719 encoder->tvout = tvout; 720 721 drm_encoder = (struct drm_encoder *) encoder; 722 723 drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; 724 drm_encoder->possible_clones = 1 << 0; 725 726 drm_encoder_init(dev, drm_encoder, 727 &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_DAC, NULL); 728 729 drm_encoder_helper_add(drm_encoder, &sti_hda_encoder_helper_funcs); 730 731 return drm_encoder; 732 } 733 734 static void sti_hdmi_encoder_enable(struct drm_encoder *encoder) 735 { 736 struct sti_tvout *tvout = to_sti_tvout(encoder); 737 738 tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode); 739 740 tvout_hdmi_start(tvout, sti_crtc_is_main(encoder->crtc)); 741 } 742 743 static void sti_hdmi_encoder_disable(struct drm_encoder *encoder) 744 { 745 struct sti_tvout *tvout = to_sti_tvout(encoder); 746 747 /* reset VIP register */ 748 tvout_write(tvout, 0x0, TVO_VIP_HDMI); 749 } 750 751 static const struct drm_encoder_helper_funcs sti_hdmi_encoder_helper_funcs = { 752 .dpms = sti_tvout_encoder_dpms, 753 .mode_set = sti_tvout_encoder_mode_set, 754 .commit = sti_hdmi_encoder_enable, 755 .disable = sti_hdmi_encoder_disable, 756 }; 757 758 static struct drm_encoder *sti_tvout_create_hdmi_encoder(struct drm_device *dev, 759 struct sti_tvout *tvout) 760 { 761 struct sti_tvout_encoder *encoder; 762 struct drm_encoder *drm_encoder; 763 764 encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL); 765 if (!encoder) 766 return NULL; 767 768 encoder->tvout = tvout; 769 770 drm_encoder = (struct drm_encoder *) encoder; 771 772 drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; 773 drm_encoder->possible_clones = 1 << 1; 774 775 drm_encoder_init(dev, drm_encoder, 776 &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); 777 778 drm_encoder_helper_add(drm_encoder, &sti_hdmi_encoder_helper_funcs); 779 780 return drm_encoder; 781 } 782 783 static void sti_tvout_create_encoders(struct drm_device *dev, 784 struct sti_tvout *tvout) 785 { 786 tvout->hdmi = sti_tvout_create_hdmi_encoder(dev, tvout); 787 tvout->hda = sti_tvout_create_hda_encoder(dev, tvout); 788 tvout->dvo = sti_tvout_create_dvo_encoder(dev, tvout); 789 } 790 791 static void sti_tvout_destroy_encoders(struct sti_tvout *tvout) 792 { 793 if (tvout->hdmi) 794 drm_encoder_cleanup(tvout->hdmi); 795 tvout->hdmi = NULL; 796 797 if (tvout->hda) 798 drm_encoder_cleanup(tvout->hda); 799 tvout->hda = NULL; 800 801 if (tvout->dvo) 802 drm_encoder_cleanup(tvout->dvo); 803 tvout->dvo = NULL; 804 } 805 806 static int sti_tvout_bind(struct device *dev, struct device *master, void *data) 807 { 808 struct sti_tvout *tvout = dev_get_drvdata(dev); 809 struct drm_device *drm_dev = data; 810 811 tvout->drm_dev = drm_dev; 812 813 sti_tvout_create_encoders(drm_dev, tvout); 814 815 return 0; 816 } 817 818 static void sti_tvout_unbind(struct device *dev, struct device *master, 819 void *data) 820 { 821 struct sti_tvout *tvout = dev_get_drvdata(dev); 822 823 sti_tvout_destroy_encoders(tvout); 824 } 825 826 static const struct component_ops sti_tvout_ops = { 827 .bind = sti_tvout_bind, 828 .unbind = sti_tvout_unbind, 829 }; 830 831 static int sti_tvout_probe(struct platform_device *pdev) 832 { 833 struct device *dev = &pdev->dev; 834 struct device_node *node = dev->of_node; 835 struct sti_tvout *tvout; 836 struct resource *res; 837 838 DRM_INFO("%s\n", __func__); 839 840 if (!node) 841 return -ENODEV; 842 843 tvout = devm_kzalloc(dev, sizeof(*tvout), GFP_KERNEL); 844 if (!tvout) 845 return -ENOMEM; 846 847 tvout->dev = dev; 848 849 /* get memory resources */ 850 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tvout-reg"); 851 if (!res) { 852 DRM_ERROR("Invalid glue resource\n"); 853 return -ENOMEM; 854 } 855 tvout->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); 856 if (!tvout->regs) 857 return -ENOMEM; 858 859 /* get reset resources */ 860 tvout->reset = devm_reset_control_get(dev, "tvout"); 861 /* take tvout out of reset */ 862 if (!IS_ERR(tvout->reset)) 863 reset_control_deassert(tvout->reset); 864 865 platform_set_drvdata(pdev, tvout); 866 867 return component_add(dev, &sti_tvout_ops); 868 } 869 870 static int sti_tvout_remove(struct platform_device *pdev) 871 { 872 component_del(&pdev->dev, &sti_tvout_ops); 873 return 0; 874 } 875 876 static const struct of_device_id tvout_of_match[] = { 877 { .compatible = "st,stih407-tvout", }, 878 { /* end node */ } 879 }; 880 MODULE_DEVICE_TABLE(of, tvout_of_match); 881 882 struct platform_driver sti_tvout_driver = { 883 .driver = { 884 .name = "sti-tvout", 885 .owner = THIS_MODULE, 886 .of_match_table = tvout_of_match, 887 }, 888 .probe = sti_tvout_probe, 889 .remove = sti_tvout_remove, 890 }; 891 892 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 893 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 894 MODULE_LICENSE("GPL"); 895