1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2016 Maxime Ripard 4 * 5 * Maxime Ripard <maxime.ripard@free-electrons.com> 6 */ 7 8 #include <linux/clk.h> 9 #include <linux/component.h> 10 #include <linux/i2c.h> 11 #include <linux/iopoll.h> 12 #include <linux/module.h> 13 #include <linux/of.h> 14 #include <linux/platform_device.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/regmap.h> 17 #include <linux/reset.h> 18 19 #include <drm/drm_atomic.h> 20 #include <drm/drm_atomic_helper.h> 21 #include <drm/drm_edid.h> 22 #include <drm/drm_encoder.h> 23 #include <drm/drm_of.h> 24 #include <drm/drm_panel.h> 25 #include <drm/drm_print.h> 26 #include <drm/drm_probe_helper.h> 27 #include <drm/drm_simple_kms_helper.h> 28 29 #include <drm/display/drm_hdmi_helper.h> 30 #include <drm/display/drm_hdmi_state_helper.h> 31 32 #include "sun4i_backend.h" 33 #include "sun4i_crtc.h" 34 #include "sun4i_drv.h" 35 #include "sun4i_hdmi.h" 36 37 #define drm_encoder_to_sun4i_hdmi(e) \ 38 container_of_const(e, struct sun4i_hdmi, encoder) 39 40 #define drm_connector_to_sun4i_hdmi(c) \ 41 container_of_const(c, struct sun4i_hdmi, connector) 42 43 static int sun4i_hdmi_write_infoframe(struct drm_connector *connector, 44 enum hdmi_infoframe_type type, 45 const u8 *buffer, size_t len) 46 { 47 struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); 48 int i; 49 50 if (type != HDMI_INFOFRAME_TYPE_AVI) { 51 drm_err(connector->dev, 52 "Unsupported infoframe type: %u\n", type); 53 return 0; 54 } 55 56 for (i = 0; i < len; i++) 57 writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i)); 58 59 return 0; 60 61 } 62 63 static void sun4i_hdmi_disable(struct drm_encoder *encoder, 64 struct drm_atomic_state *state) 65 { 66 struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder); 67 u32 val; 68 69 DRM_DEBUG_DRIVER("Disabling the HDMI Output\n"); 70 71 val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG); 72 val &= ~SUN4I_HDMI_VID_CTRL_ENABLE; 73 writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG); 74 75 clk_disable_unprepare(hdmi->tmds_clk); 76 } 77 78 static void sun4i_hdmi_enable(struct drm_encoder *encoder, 79 struct drm_atomic_state *state) 80 { 81 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; 82 struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder); 83 struct drm_connector *connector = &hdmi->connector; 84 struct drm_display_info *display = &connector->display_info; 85 struct drm_connector_state *conn_state = 86 drm_atomic_get_new_connector_state(state, connector); 87 unsigned long long tmds_rate = conn_state->hdmi.tmds_char_rate; 88 unsigned int x, y; 89 u32 val = 0; 90 91 DRM_DEBUG_DRIVER("Enabling the HDMI Output\n"); 92 93 clk_set_rate(hdmi->mod_clk, tmds_rate); 94 clk_set_rate(hdmi->tmds_clk, tmds_rate); 95 96 /* Set input sync enable */ 97 writel(SUN4I_HDMI_UNKNOWN_INPUT_SYNC, 98 hdmi->base + SUN4I_HDMI_UNKNOWN_REG); 99 100 /* 101 * Setup output pad (?) controls 102 * 103 * This is done here instead of at probe/bind time because 104 * the controller seems to toggle some of the bits on its own. 105 * 106 * We can't just initialize the register there, we need to 107 * protect the clock bits that have already been read out and 108 * cached by the clock framework. 109 */ 110 val = readl(hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG); 111 val &= SUN4I_HDMI_PAD_CTRL1_HALVE_CLK; 112 val |= hdmi->variant->pad_ctrl1_init_val; 113 writel(val, hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG); 114 val = readl(hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG); 115 116 /* Setup timing registers */ 117 writel(SUN4I_HDMI_VID_TIMING_X(mode->hdisplay) | 118 SUN4I_HDMI_VID_TIMING_Y(mode->vdisplay), 119 hdmi->base + SUN4I_HDMI_VID_TIMING_ACT_REG); 120 121 x = mode->htotal - mode->hsync_start; 122 y = mode->vtotal - mode->vsync_start; 123 writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y), 124 hdmi->base + SUN4I_HDMI_VID_TIMING_BP_REG); 125 126 x = mode->hsync_start - mode->hdisplay; 127 y = mode->vsync_start - mode->vdisplay; 128 writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y), 129 hdmi->base + SUN4I_HDMI_VID_TIMING_FP_REG); 130 131 x = mode->hsync_end - mode->hsync_start; 132 y = mode->vsync_end - mode->vsync_start; 133 writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y), 134 hdmi->base + SUN4I_HDMI_VID_TIMING_SPW_REG); 135 136 val = SUN4I_HDMI_VID_TIMING_POL_TX_CLK; 137 if (mode->flags & DRM_MODE_FLAG_PHSYNC) 138 val |= SUN4I_HDMI_VID_TIMING_POL_HSYNC; 139 140 if (mode->flags & DRM_MODE_FLAG_PVSYNC) 141 val |= SUN4I_HDMI_VID_TIMING_POL_VSYNC; 142 143 writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG); 144 145 clk_prepare_enable(hdmi->tmds_clk); 146 147 drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); 148 149 val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI); 150 val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END); 151 writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0)); 152 153 val = SUN4I_HDMI_VID_CTRL_ENABLE; 154 if (display->is_hdmi) 155 val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE; 156 157 writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG); 158 } 159 160 static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = { 161 .atomic_disable = sun4i_hdmi_disable, 162 .atomic_enable = sun4i_hdmi_enable, 163 }; 164 165 static enum drm_mode_status 166 sun4i_hdmi_connector_clock_valid(const struct drm_connector *connector, 167 const struct drm_display_mode *mode, 168 unsigned long long clock) 169 { 170 const struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); 171 unsigned long diff = div_u64(clock, 200); /* +-0.5% allowed by HDMI spec */ 172 long rounded_rate; 173 174 if (mode->flags & DRM_MODE_FLAG_DBLCLK) 175 return MODE_BAD; 176 177 /* 165 MHz is the typical max pixelclock frequency for HDMI <= 1.2 */ 178 if (clock > 165000000) 179 return MODE_CLOCK_HIGH; 180 181 rounded_rate = clk_round_rate(hdmi->tmds_clk, clock); 182 if (rounded_rate > 0 && 183 max_t(unsigned long, rounded_rate, clock) - 184 min_t(unsigned long, rounded_rate, clock) < diff) 185 return MODE_OK; 186 187 return MODE_NOCLOCK; 188 } 189 190 static int sun4i_hdmi_connector_atomic_check(struct drm_connector *connector, 191 struct drm_atomic_state *state) 192 { 193 struct drm_connector_state *conn_state = 194 drm_atomic_get_new_connector_state(state, connector); 195 struct drm_crtc *crtc = conn_state->crtc; 196 struct drm_crtc_state *crtc_state = crtc->state; 197 struct drm_display_mode *mode = &crtc_state->adjusted_mode; 198 enum drm_mode_status status; 199 200 status = sun4i_hdmi_connector_clock_valid(connector, mode, 201 conn_state->hdmi.tmds_char_rate); 202 if (status != MODE_OK) 203 return -EINVAL; 204 205 return 0; 206 } 207 208 static enum drm_mode_status 209 sun4i_hdmi_connector_mode_valid(struct drm_connector *connector, 210 struct drm_display_mode *mode) 211 { 212 unsigned long long rate = drm_hdmi_compute_mode_clock(mode, 8, 213 HDMI_COLORSPACE_RGB); 214 215 return sun4i_hdmi_connector_clock_valid(connector, mode, rate); 216 } 217 218 static int sun4i_hdmi_get_modes(struct drm_connector *connector) 219 { 220 struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); 221 const struct drm_edid *drm_edid; 222 int ret; 223 224 drm_edid = drm_edid_read_ddc(connector, hdmi->ddc_i2c ?: hdmi->i2c); 225 226 drm_edid_connector_update(connector, drm_edid); 227 cec_s_phys_addr(hdmi->cec_adap, 228 connector->display_info.source_physical_address, false); 229 230 if (!drm_edid) 231 return 0; 232 233 DRM_DEBUG_DRIVER("Monitor is %s monitor\n", 234 connector->display_info.is_hdmi ? "an HDMI" : "a DVI"); 235 236 237 ret = drm_edid_connector_add_modes(connector); 238 drm_edid_free(drm_edid); 239 240 return ret; 241 } 242 243 static struct i2c_adapter *sun4i_hdmi_get_ddc(struct device *dev) 244 { 245 struct device_node *phandle, *remote; 246 struct i2c_adapter *ddc; 247 248 remote = of_graph_get_remote_node(dev->of_node, 1, -1); 249 if (!remote) 250 return ERR_PTR(-EINVAL); 251 252 phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0); 253 of_node_put(remote); 254 if (!phandle) 255 return ERR_PTR(-ENODEV); 256 257 ddc = of_get_i2c_adapter_by_node(phandle); 258 of_node_put(phandle); 259 if (!ddc) 260 return ERR_PTR(-EPROBE_DEFER); 261 262 return ddc; 263 } 264 265 static const struct drm_connector_hdmi_funcs sun4i_hdmi_hdmi_connector_funcs = { 266 .tmds_char_rate_valid = sun4i_hdmi_connector_clock_valid, 267 .write_infoframe = sun4i_hdmi_write_infoframe, 268 }; 269 270 static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = { 271 .atomic_check = sun4i_hdmi_connector_atomic_check, 272 .mode_valid = sun4i_hdmi_connector_mode_valid, 273 .get_modes = sun4i_hdmi_get_modes, 274 }; 275 276 static enum drm_connector_status 277 sun4i_hdmi_connector_detect(struct drm_connector *connector, bool force) 278 { 279 struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); 280 unsigned long reg; 281 282 reg = readl(hdmi->base + SUN4I_HDMI_HPD_REG); 283 if (!(reg & SUN4I_HDMI_HPD_HIGH)) { 284 cec_phys_addr_invalidate(hdmi->cec_adap); 285 return connector_status_disconnected; 286 } 287 288 return connector_status_connected; 289 } 290 291 static void sun4i_hdmi_connector_reset(struct drm_connector *connector) 292 { 293 drm_atomic_helper_connector_reset(connector); 294 __drm_atomic_helper_connector_hdmi_reset(connector, connector->state); 295 } 296 297 static const struct drm_connector_funcs sun4i_hdmi_connector_funcs = { 298 .detect = sun4i_hdmi_connector_detect, 299 .fill_modes = drm_helper_probe_single_connector_modes, 300 .reset = sun4i_hdmi_connector_reset, 301 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 302 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 303 }; 304 305 #ifdef CONFIG_DRM_SUN4I_HDMI_CEC 306 static int sun4i_hdmi_cec_pin_read(struct cec_adapter *adap) 307 { 308 struct sun4i_hdmi *hdmi = cec_get_drvdata(adap); 309 310 return readl(hdmi->base + SUN4I_HDMI_CEC) & SUN4I_HDMI_CEC_RX; 311 } 312 313 static void sun4i_hdmi_cec_pin_low(struct cec_adapter *adap) 314 { 315 struct sun4i_hdmi *hdmi = cec_get_drvdata(adap); 316 317 /* Start driving the CEC pin low */ 318 writel(SUN4I_HDMI_CEC_ENABLE, hdmi->base + SUN4I_HDMI_CEC); 319 } 320 321 static void sun4i_hdmi_cec_pin_high(struct cec_adapter *adap) 322 { 323 struct sun4i_hdmi *hdmi = cec_get_drvdata(adap); 324 325 /* 326 * Stop driving the CEC pin, the pull up will take over 327 * unless another CEC device is driving the pin low. 328 */ 329 writel(0, hdmi->base + SUN4I_HDMI_CEC); 330 } 331 332 static const struct cec_pin_ops sun4i_hdmi_cec_pin_ops = { 333 .read = sun4i_hdmi_cec_pin_read, 334 .low = sun4i_hdmi_cec_pin_low, 335 .high = sun4i_hdmi_cec_pin_high, 336 }; 337 #endif 338 339 #define SUN4I_HDMI_PAD_CTRL1_MASK (GENMASK(24, 7) | GENMASK(5, 0)) 340 #define SUN4I_HDMI_PLL_CTRL_MASK (GENMASK(31, 8) | GENMASK(3, 0)) 341 342 /* Only difference from sun5i is AMP is 4 instead of 6 */ 343 static const struct sun4i_hdmi_variant sun4i_variant = { 344 .pad_ctrl0_init_val = SUN4I_HDMI_PAD_CTRL0_TXEN | 345 SUN4I_HDMI_PAD_CTRL0_CKEN | 346 SUN4I_HDMI_PAD_CTRL0_PWENG | 347 SUN4I_HDMI_PAD_CTRL0_PWEND | 348 SUN4I_HDMI_PAD_CTRL0_PWENC | 349 SUN4I_HDMI_PAD_CTRL0_LDODEN | 350 SUN4I_HDMI_PAD_CTRL0_LDOCEN | 351 SUN4I_HDMI_PAD_CTRL0_BIASEN, 352 .pad_ctrl1_init_val = SUN4I_HDMI_PAD_CTRL1_REG_AMP(4) | 353 SUN4I_HDMI_PAD_CTRL1_REG_EMP(2) | 354 SUN4I_HDMI_PAD_CTRL1_REG_DENCK | 355 SUN4I_HDMI_PAD_CTRL1_REG_DEN | 356 SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT | 357 SUN4I_HDMI_PAD_CTRL1_EMP_OPT | 358 SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT | 359 SUN4I_HDMI_PAD_CTRL1_AMP_OPT, 360 .pll_ctrl_init_val = SUN4I_HDMI_PLL_CTRL_VCO_S(8) | 361 SUN4I_HDMI_PLL_CTRL_CS(7) | 362 SUN4I_HDMI_PLL_CTRL_CP_S(15) | 363 SUN4I_HDMI_PLL_CTRL_S(7) | 364 SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) | 365 SUN4I_HDMI_PLL_CTRL_SDIV2 | 366 SUN4I_HDMI_PLL_CTRL_LDO2_EN | 367 SUN4I_HDMI_PLL_CTRL_LDO1_EN | 368 SUN4I_HDMI_PLL_CTRL_HV_IS_33 | 369 SUN4I_HDMI_PLL_CTRL_BWS | 370 SUN4I_HDMI_PLL_CTRL_PLL_EN, 371 372 .ddc_clk_reg = REG_FIELD(SUN4I_HDMI_DDC_CLK_REG, 0, 6), 373 .ddc_clk_pre_divider = 2, 374 .ddc_clk_m_offset = 1, 375 376 .field_ddc_en = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 31, 31), 377 .field_ddc_start = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 30, 30), 378 .field_ddc_reset = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 0, 0), 379 .field_ddc_addr_reg = REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 31), 380 .field_ddc_slave_addr = REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 6), 381 .field_ddc_int_status = REG_FIELD(SUN4I_HDMI_DDC_INT_STATUS_REG, 0, 8), 382 .field_ddc_fifo_clear = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 31, 31), 383 .field_ddc_fifo_rx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 4, 7), 384 .field_ddc_fifo_tx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 0, 3), 385 .field_ddc_byte_count = REG_FIELD(SUN4I_HDMI_DDC_BYTE_COUNT_REG, 0, 9), 386 .field_ddc_cmd = REG_FIELD(SUN4I_HDMI_DDC_CMD_REG, 0, 2), 387 .field_ddc_sda_en = REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 9, 9), 388 .field_ddc_sck_en = REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 8, 8), 389 390 .ddc_fifo_reg = SUN4I_HDMI_DDC_FIFO_DATA_REG, 391 .ddc_fifo_has_dir = true, 392 }; 393 394 static const struct sun4i_hdmi_variant sun5i_variant = { 395 .pad_ctrl0_init_val = SUN4I_HDMI_PAD_CTRL0_TXEN | 396 SUN4I_HDMI_PAD_CTRL0_CKEN | 397 SUN4I_HDMI_PAD_CTRL0_PWENG | 398 SUN4I_HDMI_PAD_CTRL0_PWEND | 399 SUN4I_HDMI_PAD_CTRL0_PWENC | 400 SUN4I_HDMI_PAD_CTRL0_LDODEN | 401 SUN4I_HDMI_PAD_CTRL0_LDOCEN | 402 SUN4I_HDMI_PAD_CTRL0_BIASEN, 403 .pad_ctrl1_init_val = SUN4I_HDMI_PAD_CTRL1_REG_AMP(6) | 404 SUN4I_HDMI_PAD_CTRL1_REG_EMP(2) | 405 SUN4I_HDMI_PAD_CTRL1_REG_DENCK | 406 SUN4I_HDMI_PAD_CTRL1_REG_DEN | 407 SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT | 408 SUN4I_HDMI_PAD_CTRL1_EMP_OPT | 409 SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT | 410 SUN4I_HDMI_PAD_CTRL1_AMP_OPT, 411 .pll_ctrl_init_val = SUN4I_HDMI_PLL_CTRL_VCO_S(8) | 412 SUN4I_HDMI_PLL_CTRL_CS(7) | 413 SUN4I_HDMI_PLL_CTRL_CP_S(15) | 414 SUN4I_HDMI_PLL_CTRL_S(7) | 415 SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) | 416 SUN4I_HDMI_PLL_CTRL_SDIV2 | 417 SUN4I_HDMI_PLL_CTRL_LDO2_EN | 418 SUN4I_HDMI_PLL_CTRL_LDO1_EN | 419 SUN4I_HDMI_PLL_CTRL_HV_IS_33 | 420 SUN4I_HDMI_PLL_CTRL_BWS | 421 SUN4I_HDMI_PLL_CTRL_PLL_EN, 422 423 .ddc_clk_reg = REG_FIELD(SUN4I_HDMI_DDC_CLK_REG, 0, 6), 424 .ddc_clk_pre_divider = 2, 425 .ddc_clk_m_offset = 1, 426 427 .field_ddc_en = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 31, 31), 428 .field_ddc_start = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 30, 30), 429 .field_ddc_reset = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 0, 0), 430 .field_ddc_addr_reg = REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 31), 431 .field_ddc_slave_addr = REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 6), 432 .field_ddc_int_status = REG_FIELD(SUN4I_HDMI_DDC_INT_STATUS_REG, 0, 8), 433 .field_ddc_fifo_clear = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 31, 31), 434 .field_ddc_fifo_rx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 4, 7), 435 .field_ddc_fifo_tx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 0, 3), 436 .field_ddc_byte_count = REG_FIELD(SUN4I_HDMI_DDC_BYTE_COUNT_REG, 0, 9), 437 .field_ddc_cmd = REG_FIELD(SUN4I_HDMI_DDC_CMD_REG, 0, 2), 438 .field_ddc_sda_en = REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 9, 9), 439 .field_ddc_sck_en = REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 8, 8), 440 441 .ddc_fifo_reg = SUN4I_HDMI_DDC_FIFO_DATA_REG, 442 .ddc_fifo_has_dir = true, 443 }; 444 445 static const struct sun4i_hdmi_variant sun6i_variant = { 446 .has_ddc_parent_clk = true, 447 .has_reset_control = true, 448 .pad_ctrl0_init_val = 0xff | 449 SUN4I_HDMI_PAD_CTRL0_TXEN | 450 SUN4I_HDMI_PAD_CTRL0_CKEN | 451 SUN4I_HDMI_PAD_CTRL0_PWENG | 452 SUN4I_HDMI_PAD_CTRL0_PWEND | 453 SUN4I_HDMI_PAD_CTRL0_PWENC | 454 SUN4I_HDMI_PAD_CTRL0_LDODEN | 455 SUN4I_HDMI_PAD_CTRL0_LDOCEN, 456 .pad_ctrl1_init_val = SUN4I_HDMI_PAD_CTRL1_REG_AMP(6) | 457 SUN4I_HDMI_PAD_CTRL1_REG_EMP(4) | 458 SUN4I_HDMI_PAD_CTRL1_REG_DENCK | 459 SUN4I_HDMI_PAD_CTRL1_REG_DEN | 460 SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT | 461 SUN4I_HDMI_PAD_CTRL1_EMP_OPT | 462 SUN4I_HDMI_PAD_CTRL1_PWSDT | 463 SUN4I_HDMI_PAD_CTRL1_PWSCK | 464 SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT | 465 SUN4I_HDMI_PAD_CTRL1_AMP_OPT | 466 SUN4I_HDMI_PAD_CTRL1_UNKNOWN, 467 .pll_ctrl_init_val = SUN4I_HDMI_PLL_CTRL_VCO_S(8) | 468 SUN4I_HDMI_PLL_CTRL_CS(3) | 469 SUN4I_HDMI_PLL_CTRL_CP_S(10) | 470 SUN4I_HDMI_PLL_CTRL_S(4) | 471 SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) | 472 SUN4I_HDMI_PLL_CTRL_SDIV2 | 473 SUN4I_HDMI_PLL_CTRL_LDO2_EN | 474 SUN4I_HDMI_PLL_CTRL_LDO1_EN | 475 SUN4I_HDMI_PLL_CTRL_HV_IS_33 | 476 SUN4I_HDMI_PLL_CTRL_PLL_EN, 477 478 .ddc_clk_reg = REG_FIELD(SUN6I_HDMI_DDC_CLK_REG, 0, 6), 479 .ddc_clk_pre_divider = 1, 480 .ddc_clk_m_offset = 2, 481 482 .tmds_clk_div_offset = 1, 483 484 .field_ddc_en = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 0, 0), 485 .field_ddc_start = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 27, 27), 486 .field_ddc_reset = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 31, 31), 487 .field_ddc_addr_reg = REG_FIELD(SUN6I_HDMI_DDC_ADDR_REG, 1, 31), 488 .field_ddc_slave_addr = REG_FIELD(SUN6I_HDMI_DDC_ADDR_REG, 1, 7), 489 .field_ddc_int_status = REG_FIELD(SUN6I_HDMI_DDC_INT_STATUS_REG, 0, 8), 490 .field_ddc_fifo_clear = REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 18, 18), 491 .field_ddc_fifo_rx_thres = REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 4, 7), 492 .field_ddc_fifo_tx_thres = REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 0, 3), 493 .field_ddc_byte_count = REG_FIELD(SUN6I_HDMI_DDC_CMD_REG, 16, 25), 494 .field_ddc_cmd = REG_FIELD(SUN6I_HDMI_DDC_CMD_REG, 0, 2), 495 .field_ddc_sda_en = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 6, 6), 496 .field_ddc_sck_en = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 4, 4), 497 498 .ddc_fifo_reg = SUN6I_HDMI_DDC_FIFO_DATA_REG, 499 .ddc_fifo_thres_incl = true, 500 }; 501 502 static const struct regmap_config sun4i_hdmi_regmap_config = { 503 .reg_bits = 32, 504 .val_bits = 32, 505 .reg_stride = 4, 506 .max_register = 0x580, 507 }; 508 509 static int sun4i_hdmi_bind(struct device *dev, struct device *master, 510 void *data) 511 { 512 struct platform_device *pdev = to_platform_device(dev); 513 struct drm_device *drm = data; 514 struct cec_connector_info conn_info; 515 struct sun4i_drv *drv = drm->dev_private; 516 struct sun4i_hdmi *hdmi; 517 u32 reg; 518 int ret; 519 520 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); 521 if (!hdmi) 522 return -ENOMEM; 523 dev_set_drvdata(dev, hdmi); 524 hdmi->dev = dev; 525 hdmi->drv = drv; 526 527 hdmi->variant = of_device_get_match_data(dev); 528 if (!hdmi->variant) 529 return -EINVAL; 530 531 hdmi->base = devm_platform_ioremap_resource(pdev, 0); 532 if (IS_ERR(hdmi->base)) { 533 dev_err(dev, "Couldn't map the HDMI encoder registers\n"); 534 return PTR_ERR(hdmi->base); 535 } 536 537 if (hdmi->variant->has_reset_control) { 538 hdmi->reset = devm_reset_control_get(dev, NULL); 539 if (IS_ERR(hdmi->reset)) { 540 dev_err(dev, "Couldn't get the HDMI reset control\n"); 541 return PTR_ERR(hdmi->reset); 542 } 543 544 ret = reset_control_deassert(hdmi->reset); 545 if (ret) { 546 dev_err(dev, "Couldn't deassert HDMI reset\n"); 547 return ret; 548 } 549 } 550 551 hdmi->bus_clk = devm_clk_get(dev, "ahb"); 552 if (IS_ERR(hdmi->bus_clk)) { 553 dev_err(dev, "Couldn't get the HDMI bus clock\n"); 554 ret = PTR_ERR(hdmi->bus_clk); 555 goto err_assert_reset; 556 } 557 clk_prepare_enable(hdmi->bus_clk); 558 559 hdmi->mod_clk = devm_clk_get(dev, "mod"); 560 if (IS_ERR(hdmi->mod_clk)) { 561 dev_err(dev, "Couldn't get the HDMI mod clock\n"); 562 ret = PTR_ERR(hdmi->mod_clk); 563 goto err_disable_bus_clk; 564 } 565 clk_prepare_enable(hdmi->mod_clk); 566 567 hdmi->pll0_clk = devm_clk_get(dev, "pll-0"); 568 if (IS_ERR(hdmi->pll0_clk)) { 569 dev_err(dev, "Couldn't get the HDMI PLL 0 clock\n"); 570 ret = PTR_ERR(hdmi->pll0_clk); 571 goto err_disable_mod_clk; 572 } 573 574 hdmi->pll1_clk = devm_clk_get(dev, "pll-1"); 575 if (IS_ERR(hdmi->pll1_clk)) { 576 dev_err(dev, "Couldn't get the HDMI PLL 1 clock\n"); 577 ret = PTR_ERR(hdmi->pll1_clk); 578 goto err_disable_mod_clk; 579 } 580 581 hdmi->regmap = devm_regmap_init_mmio(dev, hdmi->base, 582 &sun4i_hdmi_regmap_config); 583 if (IS_ERR(hdmi->regmap)) { 584 dev_err(dev, "Couldn't create HDMI encoder regmap\n"); 585 ret = PTR_ERR(hdmi->regmap); 586 goto err_disable_mod_clk; 587 } 588 589 ret = sun4i_tmds_create(hdmi); 590 if (ret) { 591 dev_err(dev, "Couldn't create the TMDS clock\n"); 592 goto err_disable_mod_clk; 593 } 594 595 if (hdmi->variant->has_ddc_parent_clk) { 596 hdmi->ddc_parent_clk = devm_clk_get(dev, "ddc"); 597 if (IS_ERR(hdmi->ddc_parent_clk)) { 598 dev_err(dev, "Couldn't get the HDMI DDC clock\n"); 599 ret = PTR_ERR(hdmi->ddc_parent_clk); 600 goto err_disable_mod_clk; 601 } 602 } else { 603 hdmi->ddc_parent_clk = hdmi->tmds_clk; 604 } 605 606 writel(SUN4I_HDMI_CTRL_ENABLE, hdmi->base + SUN4I_HDMI_CTRL_REG); 607 608 writel(hdmi->variant->pad_ctrl0_init_val, 609 hdmi->base + SUN4I_HDMI_PAD_CTRL0_REG); 610 611 reg = readl(hdmi->base + SUN4I_HDMI_PLL_CTRL_REG); 612 reg &= SUN4I_HDMI_PLL_CTRL_DIV_MASK; 613 reg |= hdmi->variant->pll_ctrl_init_val; 614 writel(reg, hdmi->base + SUN4I_HDMI_PLL_CTRL_REG); 615 616 ret = sun4i_hdmi_i2c_create(dev, hdmi); 617 if (ret) { 618 dev_err(dev, "Couldn't create the HDMI I2C adapter\n"); 619 goto err_disable_mod_clk; 620 } 621 622 hdmi->ddc_i2c = sun4i_hdmi_get_ddc(dev); 623 if (IS_ERR(hdmi->ddc_i2c)) { 624 ret = PTR_ERR(hdmi->ddc_i2c); 625 if (ret == -ENODEV) 626 hdmi->ddc_i2c = NULL; 627 else 628 goto err_del_i2c_adapter; 629 } 630 631 drm_encoder_helper_add(&hdmi->encoder, 632 &sun4i_hdmi_helper_funcs); 633 ret = drm_simple_encoder_init(drm, &hdmi->encoder, 634 DRM_MODE_ENCODER_TMDS); 635 if (ret) { 636 dev_err(dev, "Couldn't initialise the HDMI encoder\n"); 637 goto err_put_ddc_i2c; 638 } 639 640 hdmi->encoder.possible_crtcs = drm_of_find_possible_crtcs(drm, 641 dev->of_node); 642 if (!hdmi->encoder.possible_crtcs) { 643 ret = -EPROBE_DEFER; 644 goto err_put_ddc_i2c; 645 } 646 647 #ifdef CONFIG_DRM_SUN4I_HDMI_CEC 648 hdmi->cec_adap = cec_pin_allocate_adapter(&sun4i_hdmi_cec_pin_ops, 649 hdmi, "sun4i", CEC_CAP_DEFAULTS | CEC_CAP_CONNECTOR_INFO); 650 ret = PTR_ERR_OR_ZERO(hdmi->cec_adap); 651 if (ret < 0) 652 goto err_cleanup_connector; 653 writel(readl(hdmi->base + SUN4I_HDMI_CEC) & ~SUN4I_HDMI_CEC_TX, 654 hdmi->base + SUN4I_HDMI_CEC); 655 #endif 656 657 drm_connector_helper_add(&hdmi->connector, 658 &sun4i_hdmi_connector_helper_funcs); 659 ret = drmm_connector_hdmi_init(drm, &hdmi->connector, 660 /* 661 * NOTE: Those are likely to be 662 * wrong, but I couldn't find the 663 * actual ones in the BSP. 664 */ 665 "AW", "HDMI", 666 &sun4i_hdmi_connector_funcs, 667 &sun4i_hdmi_hdmi_connector_funcs, 668 DRM_MODE_CONNECTOR_HDMIA, 669 hdmi->ddc_i2c, 670 BIT(HDMI_COLORSPACE_RGB), 671 8); 672 if (ret) { 673 dev_err(dev, 674 "Couldn't initialise the HDMI connector\n"); 675 goto err_cleanup_connector; 676 } 677 cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector); 678 cec_s_conn_info(hdmi->cec_adap, &conn_info); 679 680 /* There is no HPD interrupt, so we need to poll the controller */ 681 hdmi->connector.polled = DRM_CONNECTOR_POLL_CONNECT | 682 DRM_CONNECTOR_POLL_DISCONNECT; 683 684 ret = cec_register_adapter(hdmi->cec_adap, dev); 685 if (ret < 0) 686 goto err_cleanup_connector; 687 drm_connector_attach_encoder(&hdmi->connector, &hdmi->encoder); 688 689 return 0; 690 691 err_cleanup_connector: 692 cec_delete_adapter(hdmi->cec_adap); 693 drm_encoder_cleanup(&hdmi->encoder); 694 err_put_ddc_i2c: 695 i2c_put_adapter(hdmi->ddc_i2c); 696 err_del_i2c_adapter: 697 i2c_del_adapter(hdmi->i2c); 698 err_disable_mod_clk: 699 clk_disable_unprepare(hdmi->mod_clk); 700 err_disable_bus_clk: 701 clk_disable_unprepare(hdmi->bus_clk); 702 err_assert_reset: 703 reset_control_assert(hdmi->reset); 704 return ret; 705 } 706 707 static void sun4i_hdmi_unbind(struct device *dev, struct device *master, 708 void *data) 709 { 710 struct sun4i_hdmi *hdmi = dev_get_drvdata(dev); 711 712 cec_unregister_adapter(hdmi->cec_adap); 713 i2c_del_adapter(hdmi->i2c); 714 i2c_put_adapter(hdmi->ddc_i2c); 715 clk_disable_unprepare(hdmi->mod_clk); 716 clk_disable_unprepare(hdmi->bus_clk); 717 } 718 719 static const struct component_ops sun4i_hdmi_ops = { 720 .bind = sun4i_hdmi_bind, 721 .unbind = sun4i_hdmi_unbind, 722 }; 723 724 static int sun4i_hdmi_probe(struct platform_device *pdev) 725 { 726 return component_add(&pdev->dev, &sun4i_hdmi_ops); 727 } 728 729 static void sun4i_hdmi_remove(struct platform_device *pdev) 730 { 731 component_del(&pdev->dev, &sun4i_hdmi_ops); 732 } 733 734 static const struct of_device_id sun4i_hdmi_of_table[] = { 735 { .compatible = "allwinner,sun4i-a10-hdmi", .data = &sun4i_variant, }, 736 { .compatible = "allwinner,sun5i-a10s-hdmi", .data = &sun5i_variant, }, 737 { .compatible = "allwinner,sun6i-a31-hdmi", .data = &sun6i_variant, }, 738 { } 739 }; 740 MODULE_DEVICE_TABLE(of, sun4i_hdmi_of_table); 741 742 static struct platform_driver sun4i_hdmi_driver = { 743 .probe = sun4i_hdmi_probe, 744 .remove_new = sun4i_hdmi_remove, 745 .driver = { 746 .name = "sun4i-hdmi", 747 .of_match_table = sun4i_hdmi_of_table, 748 }, 749 }; 750 module_platform_driver(sun4i_hdmi_driver); 751 752 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); 753 MODULE_DESCRIPTION("Allwinner A10 HDMI Driver"); 754 MODULE_LICENSE("GPL"); 755