1 /* 2 * Copyright (C) 2016 Maxime Ripard 3 * 4 * Maxime Ripard <maxime.ripard@free-electrons.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 */ 11 12 #include <drm/drmP.h> 13 #include <drm/drm_atomic_helper.h> 14 #include <drm/drm_crtc_helper.h> 15 #include <drm/drm_edid.h> 16 #include <drm/drm_encoder.h> 17 #include <drm/drm_of.h> 18 #include <drm/drm_panel.h> 19 20 #include <linux/clk.h> 21 #include <linux/component.h> 22 #include <linux/iopoll.h> 23 #include <linux/platform_device.h> 24 #include <linux/pm_runtime.h> 25 26 #include "sun4i_backend.h" 27 #include "sun4i_crtc.h" 28 #include "sun4i_drv.h" 29 #include "sun4i_hdmi.h" 30 #include "sun4i_tcon.h" 31 32 #define DDC_SEGMENT_ADDR 0x30 33 34 static inline struct sun4i_hdmi * 35 drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder) 36 { 37 return container_of(encoder, struct sun4i_hdmi, 38 encoder); 39 } 40 41 static inline struct sun4i_hdmi * 42 drm_connector_to_sun4i_hdmi(struct drm_connector *connector) 43 { 44 return container_of(connector, struct sun4i_hdmi, 45 connector); 46 } 47 48 static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi, 49 struct drm_display_mode *mode) 50 { 51 struct hdmi_avi_infoframe frame; 52 u8 buffer[17]; 53 int i, ret; 54 55 ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 56 if (ret < 0) { 57 DRM_ERROR("Failed to get infoframes from mode\n"); 58 return ret; 59 } 60 61 ret = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); 62 if (ret < 0) { 63 DRM_ERROR("Failed to pack infoframes\n"); 64 return ret; 65 } 66 67 for (i = 0; i < sizeof(buffer); i++) 68 writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i)); 69 70 return 0; 71 } 72 73 static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder, 74 struct drm_crtc_state *crtc_state, 75 struct drm_connector_state *conn_state) 76 { 77 struct drm_display_mode *mode = &crtc_state->mode; 78 79 if (mode->flags & DRM_MODE_FLAG_DBLCLK) 80 return -EINVAL; 81 82 return 0; 83 } 84 85 static void sun4i_hdmi_disable(struct drm_encoder *encoder) 86 { 87 struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder); 88 struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); 89 struct sun4i_tcon *tcon = crtc->tcon; 90 u32 val; 91 92 DRM_DEBUG_DRIVER("Disabling the HDMI Output\n"); 93 94 val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG); 95 val &= ~SUN4I_HDMI_VID_CTRL_ENABLE; 96 writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG); 97 98 sun4i_tcon_channel_disable(tcon, 1); 99 } 100 101 static void sun4i_hdmi_enable(struct drm_encoder *encoder) 102 { 103 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; 104 struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder); 105 struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); 106 struct sun4i_tcon *tcon = crtc->tcon; 107 u32 val = 0; 108 109 DRM_DEBUG_DRIVER("Enabling the HDMI Output\n"); 110 111 sun4i_tcon_channel_enable(tcon, 1); 112 113 sun4i_hdmi_setup_avi_infoframes(hdmi, mode); 114 val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI); 115 val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END); 116 writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0)); 117 118 val = SUN4I_HDMI_VID_CTRL_ENABLE; 119 if (hdmi->hdmi_monitor) 120 val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE; 121 122 writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG); 123 } 124 125 static void sun4i_hdmi_mode_set(struct drm_encoder *encoder, 126 struct drm_display_mode *mode, 127 struct drm_display_mode *adjusted_mode) 128 { 129 struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder); 130 struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); 131 struct sun4i_tcon *tcon = crtc->tcon; 132 unsigned int x, y; 133 u32 val; 134 135 sun4i_tcon1_mode_set(tcon, mode); 136 sun4i_tcon_set_mux(tcon, 1, encoder); 137 138 clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); 139 clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000); 140 clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000); 141 142 /* Set input sync enable */ 143 writel(SUN4I_HDMI_UNKNOWN_INPUT_SYNC, 144 hdmi->base + SUN4I_HDMI_UNKNOWN_REG); 145 146 /* Setup timing registers */ 147 writel(SUN4I_HDMI_VID_TIMING_X(mode->hdisplay) | 148 SUN4I_HDMI_VID_TIMING_Y(mode->vdisplay), 149 hdmi->base + SUN4I_HDMI_VID_TIMING_ACT_REG); 150 151 x = mode->htotal - mode->hsync_start; 152 y = mode->vtotal - mode->vsync_start; 153 writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y), 154 hdmi->base + SUN4I_HDMI_VID_TIMING_BP_REG); 155 156 x = mode->hsync_start - mode->hdisplay; 157 y = mode->vsync_start - mode->vdisplay; 158 writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y), 159 hdmi->base + SUN4I_HDMI_VID_TIMING_FP_REG); 160 161 x = mode->hsync_end - mode->hsync_start; 162 y = mode->vsync_end - mode->vsync_start; 163 writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y), 164 hdmi->base + SUN4I_HDMI_VID_TIMING_SPW_REG); 165 166 val = SUN4I_HDMI_VID_TIMING_POL_TX_CLK; 167 if (mode->flags & DRM_MODE_FLAG_PHSYNC) 168 val |= SUN4I_HDMI_VID_TIMING_POL_HSYNC; 169 170 if (mode->flags & DRM_MODE_FLAG_PVSYNC) 171 val |= SUN4I_HDMI_VID_TIMING_POL_VSYNC; 172 173 writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG); 174 } 175 176 static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = { 177 .atomic_check = sun4i_hdmi_atomic_check, 178 .disable = sun4i_hdmi_disable, 179 .enable = sun4i_hdmi_enable, 180 .mode_set = sun4i_hdmi_mode_set, 181 }; 182 183 static const struct drm_encoder_funcs sun4i_hdmi_funcs = { 184 .destroy = drm_encoder_cleanup, 185 }; 186 187 static int sun4i_hdmi_read_sub_block(struct sun4i_hdmi *hdmi, 188 unsigned int blk, unsigned int offset, 189 u8 *buf, unsigned int count) 190 { 191 unsigned long reg; 192 int i; 193 194 reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 195 reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK; 196 writel(reg | SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ, 197 hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 198 199 writel(SUN4I_HDMI_DDC_ADDR_SEGMENT(offset >> 8) | 200 SUN4I_HDMI_DDC_ADDR_EDDC(DDC_SEGMENT_ADDR << 1) | 201 SUN4I_HDMI_DDC_ADDR_OFFSET(offset) | 202 SUN4I_HDMI_DDC_ADDR_SLAVE(DDC_ADDR), 203 hdmi->base + SUN4I_HDMI_DDC_ADDR_REG); 204 205 reg = readl(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); 206 writel(reg | SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR, 207 hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); 208 209 writel(count, hdmi->base + SUN4I_HDMI_DDC_BYTE_COUNT_REG); 210 writel(SUN4I_HDMI_DDC_CMD_EXPLICIT_EDDC_READ, 211 hdmi->base + SUN4I_HDMI_DDC_CMD_REG); 212 213 reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 214 writel(reg | SUN4I_HDMI_DDC_CTRL_START_CMD, 215 hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 216 217 if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, reg, 218 !(reg & SUN4I_HDMI_DDC_CTRL_START_CMD), 219 100, 100000)) 220 return -EIO; 221 222 for (i = 0; i < count; i++) 223 buf[i] = readb(hdmi->base + SUN4I_HDMI_DDC_FIFO_DATA_REG); 224 225 return 0; 226 } 227 228 static int sun4i_hdmi_read_edid_block(void *data, u8 *buf, unsigned int blk, 229 size_t length) 230 { 231 struct sun4i_hdmi *hdmi = data; 232 int retry = 2, i; 233 234 do { 235 for (i = 0; i < length; i += SUN4I_HDMI_DDC_FIFO_SIZE) { 236 unsigned char offset = blk * EDID_LENGTH + i; 237 unsigned int count = min((unsigned int)SUN4I_HDMI_DDC_FIFO_SIZE, 238 length - i); 239 int ret; 240 241 ret = sun4i_hdmi_read_sub_block(hdmi, blk, offset, 242 buf + i, count); 243 if (ret) 244 return ret; 245 } 246 } while (!drm_edid_block_valid(buf, blk, true, NULL) && (retry--)); 247 248 return 0; 249 } 250 251 static int sun4i_hdmi_get_modes(struct drm_connector *connector) 252 { 253 struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); 254 unsigned long reg; 255 struct edid *edid; 256 int ret; 257 258 /* Reset i2c controller */ 259 writel(SUN4I_HDMI_DDC_CTRL_ENABLE | SUN4I_HDMI_DDC_CTRL_RESET, 260 hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 261 if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, reg, 262 !(reg & SUN4I_HDMI_DDC_CTRL_RESET), 263 100, 2000)) 264 return -EIO; 265 266 writel(SUN4I_HDMI_DDC_LINE_CTRL_SDA_ENABLE | 267 SUN4I_HDMI_DDC_LINE_CTRL_SCL_ENABLE, 268 hdmi->base + SUN4I_HDMI_DDC_LINE_CTRL_REG); 269 270 clk_prepare_enable(hdmi->ddc_clk); 271 clk_set_rate(hdmi->ddc_clk, 100000); 272 273 edid = drm_do_get_edid(connector, sun4i_hdmi_read_edid_block, hdmi); 274 if (!edid) 275 return 0; 276 277 hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid); 278 DRM_DEBUG_DRIVER("Monitor is %s monitor\n", 279 hdmi->hdmi_monitor ? "an HDMI" : "a DVI"); 280 281 drm_mode_connector_update_edid_property(connector, edid); 282 ret = drm_add_edid_modes(connector, edid); 283 kfree(edid); 284 285 clk_disable_unprepare(hdmi->ddc_clk); 286 287 return ret; 288 } 289 290 static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = { 291 .get_modes = sun4i_hdmi_get_modes, 292 }; 293 294 static enum drm_connector_status 295 sun4i_hdmi_connector_detect(struct drm_connector *connector, bool force) 296 { 297 struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); 298 unsigned long reg; 299 300 if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_HPD_REG, reg, 301 reg & SUN4I_HDMI_HPD_HIGH, 302 0, 500000)) 303 return connector_status_disconnected; 304 305 return connector_status_connected; 306 } 307 308 static const struct drm_connector_funcs sun4i_hdmi_connector_funcs = { 309 .dpms = drm_atomic_helper_connector_dpms, 310 .detect = sun4i_hdmi_connector_detect, 311 .fill_modes = drm_helper_probe_single_connector_modes, 312 .destroy = drm_connector_cleanup, 313 .reset = drm_atomic_helper_connector_reset, 314 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 315 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 316 }; 317 318 static int sun4i_hdmi_bind(struct device *dev, struct device *master, 319 void *data) 320 { 321 struct platform_device *pdev = to_platform_device(dev); 322 struct drm_device *drm = data; 323 struct sun4i_drv *drv = drm->dev_private; 324 struct sun4i_hdmi *hdmi; 325 struct resource *res; 326 u32 reg; 327 int ret; 328 329 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); 330 if (!hdmi) 331 return -ENOMEM; 332 dev_set_drvdata(dev, hdmi); 333 hdmi->dev = dev; 334 hdmi->drv = drv; 335 336 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 337 hdmi->base = devm_ioremap_resource(dev, res); 338 if (IS_ERR(hdmi->base)) { 339 dev_err(dev, "Couldn't map the HDMI encoder registers\n"); 340 return PTR_ERR(hdmi->base); 341 } 342 343 hdmi->bus_clk = devm_clk_get(dev, "ahb"); 344 if (IS_ERR(hdmi->bus_clk)) { 345 dev_err(dev, "Couldn't get the HDMI bus clock\n"); 346 return PTR_ERR(hdmi->bus_clk); 347 } 348 clk_prepare_enable(hdmi->bus_clk); 349 350 hdmi->mod_clk = devm_clk_get(dev, "mod"); 351 if (IS_ERR(hdmi->mod_clk)) { 352 dev_err(dev, "Couldn't get the HDMI mod clock\n"); 353 return PTR_ERR(hdmi->mod_clk); 354 } 355 clk_prepare_enable(hdmi->mod_clk); 356 357 hdmi->pll0_clk = devm_clk_get(dev, "pll-0"); 358 if (IS_ERR(hdmi->pll0_clk)) { 359 dev_err(dev, "Couldn't get the HDMI PLL 0 clock\n"); 360 return PTR_ERR(hdmi->pll0_clk); 361 } 362 363 hdmi->pll1_clk = devm_clk_get(dev, "pll-1"); 364 if (IS_ERR(hdmi->pll1_clk)) { 365 dev_err(dev, "Couldn't get the HDMI PLL 1 clock\n"); 366 return PTR_ERR(hdmi->pll1_clk); 367 } 368 369 ret = sun4i_tmds_create(hdmi); 370 if (ret) { 371 dev_err(dev, "Couldn't create the TMDS clock\n"); 372 return ret; 373 } 374 375 writel(SUN4I_HDMI_CTRL_ENABLE, hdmi->base + SUN4I_HDMI_CTRL_REG); 376 377 writel(SUN4I_HDMI_PAD_CTRL0_TXEN | SUN4I_HDMI_PAD_CTRL0_CKEN | 378 SUN4I_HDMI_PAD_CTRL0_PWENG | SUN4I_HDMI_PAD_CTRL0_PWEND | 379 SUN4I_HDMI_PAD_CTRL0_PWENC | SUN4I_HDMI_PAD_CTRL0_LDODEN | 380 SUN4I_HDMI_PAD_CTRL0_LDOCEN | SUN4I_HDMI_PAD_CTRL0_BIASEN, 381 hdmi->base + SUN4I_HDMI_PAD_CTRL0_REG); 382 383 /* 384 * We can't just initialize the register there, we need to 385 * protect the clock bits that have already been read out and 386 * cached by the clock framework. 387 */ 388 reg = readl(hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG); 389 reg &= SUN4I_HDMI_PAD_CTRL1_HALVE_CLK; 390 reg |= SUN4I_HDMI_PAD_CTRL1_REG_AMP(6) | 391 SUN4I_HDMI_PAD_CTRL1_REG_EMP(2) | 392 SUN4I_HDMI_PAD_CTRL1_REG_DENCK | 393 SUN4I_HDMI_PAD_CTRL1_REG_DEN | 394 SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT | 395 SUN4I_HDMI_PAD_CTRL1_EMP_OPT | 396 SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT | 397 SUN4I_HDMI_PAD_CTRL1_AMP_OPT; 398 writel(reg, hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG); 399 400 reg = readl(hdmi->base + SUN4I_HDMI_PLL_CTRL_REG); 401 reg &= SUN4I_HDMI_PLL_CTRL_DIV_MASK; 402 reg |= SUN4I_HDMI_PLL_CTRL_VCO_S(8) | SUN4I_HDMI_PLL_CTRL_CS(7) | 403 SUN4I_HDMI_PLL_CTRL_CP_S(15) | SUN4I_HDMI_PLL_CTRL_S(7) | 404 SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) | SUN4I_HDMI_PLL_CTRL_SDIV2 | 405 SUN4I_HDMI_PLL_CTRL_LDO2_EN | SUN4I_HDMI_PLL_CTRL_LDO1_EN | 406 SUN4I_HDMI_PLL_CTRL_HV_IS_33 | SUN4I_HDMI_PLL_CTRL_BWS | 407 SUN4I_HDMI_PLL_CTRL_PLL_EN; 408 writel(reg, hdmi->base + SUN4I_HDMI_PLL_CTRL_REG); 409 410 ret = sun4i_ddc_create(hdmi, hdmi->tmds_clk); 411 if (ret) { 412 dev_err(dev, "Couldn't create the DDC clock\n"); 413 return ret; 414 } 415 416 drm_encoder_helper_add(&hdmi->encoder, 417 &sun4i_hdmi_helper_funcs); 418 ret = drm_encoder_init(drm, 419 &hdmi->encoder, 420 &sun4i_hdmi_funcs, 421 DRM_MODE_ENCODER_TMDS, 422 NULL); 423 if (ret) { 424 dev_err(dev, "Couldn't initialise the HDMI encoder\n"); 425 return ret; 426 } 427 428 hdmi->encoder.possible_crtcs = drm_of_find_possible_crtcs(drm, 429 dev->of_node); 430 if (!hdmi->encoder.possible_crtcs) 431 return -EPROBE_DEFER; 432 433 drm_connector_helper_add(&hdmi->connector, 434 &sun4i_hdmi_connector_helper_funcs); 435 ret = drm_connector_init(drm, &hdmi->connector, 436 &sun4i_hdmi_connector_funcs, 437 DRM_MODE_CONNECTOR_HDMIA); 438 if (ret) { 439 dev_err(dev, 440 "Couldn't initialise the HDMI connector\n"); 441 goto err_cleanup_connector; 442 } 443 444 /* There is no HPD interrupt, so we need to poll the controller */ 445 hdmi->connector.polled = DRM_CONNECTOR_POLL_CONNECT | 446 DRM_CONNECTOR_POLL_DISCONNECT; 447 448 drm_mode_connector_attach_encoder(&hdmi->connector, &hdmi->encoder); 449 450 return 0; 451 452 err_cleanup_connector: 453 drm_encoder_cleanup(&hdmi->encoder); 454 return ret; 455 } 456 457 static void sun4i_hdmi_unbind(struct device *dev, struct device *master, 458 void *data) 459 { 460 struct sun4i_hdmi *hdmi = dev_get_drvdata(dev); 461 462 drm_connector_cleanup(&hdmi->connector); 463 drm_encoder_cleanup(&hdmi->encoder); 464 } 465 466 static const struct component_ops sun4i_hdmi_ops = { 467 .bind = sun4i_hdmi_bind, 468 .unbind = sun4i_hdmi_unbind, 469 }; 470 471 static int sun4i_hdmi_probe(struct platform_device *pdev) 472 { 473 return component_add(&pdev->dev, &sun4i_hdmi_ops); 474 } 475 476 static int sun4i_hdmi_remove(struct platform_device *pdev) 477 { 478 component_del(&pdev->dev, &sun4i_hdmi_ops); 479 480 return 0; 481 } 482 483 static const struct of_device_id sun4i_hdmi_of_table[] = { 484 { .compatible = "allwinner,sun5i-a10s-hdmi" }, 485 { } 486 }; 487 MODULE_DEVICE_TABLE(of, sun4i_hdmi_of_table); 488 489 static struct platform_driver sun4i_hdmi_driver = { 490 .probe = sun4i_hdmi_probe, 491 .remove = sun4i_hdmi_remove, 492 .driver = { 493 .name = "sun4i-hdmi", 494 .of_match_table = sun4i_hdmi_of_table, 495 }, 496 }; 497 module_platform_driver(sun4i_hdmi_driver); 498 499 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); 500 MODULE_DESCRIPTION("Allwinner A10 HDMI Driver"); 501 MODULE_LICENSE("GPL"); 502