Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.0-rc6 763 lines 19 kB view raw
1/* 2 * Copyright 2016 Linaro Ltd. 3 * Copyright 2016 ZTE Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 */ 10 11#include <linux/clk.h> 12#include <linux/component.h> 13#include <linux/delay.h> 14#include <linux/err.h> 15#include <linux/hdmi.h> 16#include <linux/irq.h> 17#include <linux/mfd/syscon.h> 18#include <linux/module.h> 19#include <linux/mutex.h> 20#include <linux/of_device.h> 21 22#include <drm/drm_atomic_helper.h> 23#include <drm/drm_crtc_helper.h> 24#include <drm/drm_edid.h> 25#include <drm/drm_of.h> 26#include <drm/drmP.h> 27 28#include <sound/hdmi-codec.h> 29 30#include "zx_hdmi_regs.h" 31#include "zx_vou.h" 32 33#define ZX_HDMI_INFOFRAME_SIZE 31 34#define DDC_SEGMENT_ADDR 0x30 35 36struct zx_hdmi_i2c { 37 struct i2c_adapter adap; 38 struct mutex lock; 39}; 40 41struct zx_hdmi { 42 struct drm_connector connector; 43 struct drm_encoder encoder; 44 struct zx_hdmi_i2c *ddc; 45 struct device *dev; 46 struct drm_device *drm; 47 void __iomem *mmio; 48 struct clk *cec_clk; 49 struct clk *osc_clk; 50 struct clk *xclk; 51 bool sink_is_hdmi; 52 bool sink_has_audio; 53 struct platform_device *audio_pdev; 54}; 55 56#define to_zx_hdmi(x) container_of(x, struct zx_hdmi, x) 57 58static inline u8 hdmi_readb(struct zx_hdmi *hdmi, u16 offset) 59{ 60 return readl_relaxed(hdmi->mmio + offset * 4); 61} 62 63static inline void hdmi_writeb(struct zx_hdmi *hdmi, u16 offset, u8 val) 64{ 65 writel_relaxed(val, hdmi->mmio + offset * 4); 66} 67 68static inline void hdmi_writeb_mask(struct zx_hdmi *hdmi, u16 offset, 69 u8 mask, u8 val) 70{ 71 u8 tmp; 72 73 tmp = hdmi_readb(hdmi, offset); 74 tmp = (tmp & ~mask) | (val & mask); 75 hdmi_writeb(hdmi, offset, tmp); 76} 77 78static int zx_hdmi_infoframe_trans(struct zx_hdmi *hdmi, 79 union hdmi_infoframe *frame, u8 fsel) 80{ 81 u8 buffer[ZX_HDMI_INFOFRAME_SIZE]; 82 int num; 83 int i; 84 85 hdmi_writeb(hdmi, TPI_INFO_FSEL, fsel); 86 87 num = hdmi_infoframe_pack(frame, buffer, ZX_HDMI_INFOFRAME_SIZE); 88 if (num < 0) { 89 DRM_DEV_ERROR(hdmi->dev, "failed to pack infoframe: %d\n", num); 90 return num; 91 } 92 93 for (i = 0; i < num; i++) 94 hdmi_writeb(hdmi, TPI_INFO_B0 + i, buffer[i]); 95 96 hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_RPT, 97 TPI_INFO_TRANS_RPT); 98 hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_EN, 99 TPI_INFO_TRANS_EN); 100 101 return num; 102} 103 104static int zx_hdmi_config_video_vsi(struct zx_hdmi *hdmi, 105 struct drm_display_mode *mode) 106{ 107 union hdmi_infoframe frame; 108 int ret; 109 110 ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi, 111 &hdmi->connector, 112 mode); 113 if (ret) { 114 DRM_DEV_ERROR(hdmi->dev, "failed to get vendor infoframe: %d\n", 115 ret); 116 return ret; 117 } 118 119 return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_VSIF); 120} 121 122static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi, 123 struct drm_display_mode *mode) 124{ 125 union hdmi_infoframe frame; 126 int ret; 127 128 ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); 129 if (ret) { 130 DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n", 131 ret); 132 return ret; 133 } 134 135 /* We always use YUV444 for HDMI output. */ 136 frame.avi.colorspace = HDMI_COLORSPACE_YUV444; 137 138 return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_AVI); 139} 140 141static void zx_hdmi_encoder_mode_set(struct drm_encoder *encoder, 142 struct drm_display_mode *mode, 143 struct drm_display_mode *adj_mode) 144{ 145 struct zx_hdmi *hdmi = to_zx_hdmi(encoder); 146 147 if (hdmi->sink_is_hdmi) { 148 zx_hdmi_config_video_avi(hdmi, mode); 149 zx_hdmi_config_video_vsi(hdmi, mode); 150 } 151} 152 153static void zx_hdmi_phy_start(struct zx_hdmi *hdmi) 154{ 155 /* Copy from ZTE BSP code */ 156 hdmi_writeb(hdmi, 0x222, 0x0); 157 hdmi_writeb(hdmi, 0x224, 0x4); 158 hdmi_writeb(hdmi, 0x909, 0x0); 159 hdmi_writeb(hdmi, 0x7b0, 0x90); 160 hdmi_writeb(hdmi, 0x7b1, 0x00); 161 hdmi_writeb(hdmi, 0x7b2, 0xa7); 162 hdmi_writeb(hdmi, 0x7b8, 0xaa); 163 hdmi_writeb(hdmi, 0x7b2, 0xa7); 164 hdmi_writeb(hdmi, 0x7b3, 0x0f); 165 hdmi_writeb(hdmi, 0x7b4, 0x0f); 166 hdmi_writeb(hdmi, 0x7b5, 0x55); 167 hdmi_writeb(hdmi, 0x7b7, 0x03); 168 hdmi_writeb(hdmi, 0x7b9, 0x12); 169 hdmi_writeb(hdmi, 0x7ba, 0x32); 170 hdmi_writeb(hdmi, 0x7bc, 0x68); 171 hdmi_writeb(hdmi, 0x7be, 0x40); 172 hdmi_writeb(hdmi, 0x7bf, 0x84); 173 hdmi_writeb(hdmi, 0x7c1, 0x0f); 174 hdmi_writeb(hdmi, 0x7c8, 0x02); 175 hdmi_writeb(hdmi, 0x7c9, 0x03); 176 hdmi_writeb(hdmi, 0x7ca, 0x40); 177 hdmi_writeb(hdmi, 0x7dc, 0x31); 178 hdmi_writeb(hdmi, 0x7e2, 0x04); 179 hdmi_writeb(hdmi, 0x7e0, 0x06); 180 hdmi_writeb(hdmi, 0x7cb, 0x68); 181 hdmi_writeb(hdmi, 0x7f9, 0x02); 182 hdmi_writeb(hdmi, 0x7b6, 0x02); 183 hdmi_writeb(hdmi, 0x7f3, 0x0); 184} 185 186static void zx_hdmi_hw_enable(struct zx_hdmi *hdmi) 187{ 188 /* Enable pclk */ 189 hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, CLKPWD_PDIDCK); 190 191 /* Enable HDMI for TX */ 192 hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, FUNC_HDMI_EN); 193 194 /* Enable deep color packet */ 195 hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN); 196 197 /* Enable HDMI/MHL mode for output */ 198 hdmi_writeb_mask(hdmi, TEST_TXCTRL, TEST_TXCTRL_HDMI_MODE, 199 TEST_TXCTRL_HDMI_MODE); 200 201 /* Configure reg_qc_sel */ 202 hdmi_writeb(hdmi, HDMICTL4, 0x3); 203 204 /* Enable interrupt */ 205 hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT, 206 INTR1_MONITOR_DETECT); 207 208 /* Start up phy */ 209 zx_hdmi_phy_start(hdmi); 210} 211 212static void zx_hdmi_hw_disable(struct zx_hdmi *hdmi) 213{ 214 /* Disable interrupt */ 215 hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT, 0); 216 217 /* Disable deep color packet */ 218 hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN); 219 220 /* Disable HDMI for TX */ 221 hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, 0); 222 223 /* Disable pclk */ 224 hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, 0); 225} 226 227static void zx_hdmi_encoder_enable(struct drm_encoder *encoder) 228{ 229 struct zx_hdmi *hdmi = to_zx_hdmi(encoder); 230 231 clk_prepare_enable(hdmi->cec_clk); 232 clk_prepare_enable(hdmi->osc_clk); 233 clk_prepare_enable(hdmi->xclk); 234 235 zx_hdmi_hw_enable(hdmi); 236 237 vou_inf_enable(VOU_HDMI, encoder->crtc); 238} 239 240static void zx_hdmi_encoder_disable(struct drm_encoder *encoder) 241{ 242 struct zx_hdmi *hdmi = to_zx_hdmi(encoder); 243 244 vou_inf_disable(VOU_HDMI, encoder->crtc); 245 246 zx_hdmi_hw_disable(hdmi); 247 248 clk_disable_unprepare(hdmi->xclk); 249 clk_disable_unprepare(hdmi->osc_clk); 250 clk_disable_unprepare(hdmi->cec_clk); 251} 252 253static const struct drm_encoder_helper_funcs zx_hdmi_encoder_helper_funcs = { 254 .enable = zx_hdmi_encoder_enable, 255 .disable = zx_hdmi_encoder_disable, 256 .mode_set = zx_hdmi_encoder_mode_set, 257}; 258 259static const struct drm_encoder_funcs zx_hdmi_encoder_funcs = { 260 .destroy = drm_encoder_cleanup, 261}; 262 263static int zx_hdmi_connector_get_modes(struct drm_connector *connector) 264{ 265 struct zx_hdmi *hdmi = to_zx_hdmi(connector); 266 struct edid *edid; 267 int ret; 268 269 edid = drm_get_edid(connector, &hdmi->ddc->adap); 270 if (!edid) 271 return 0; 272 273 hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); 274 hdmi->sink_has_audio = drm_detect_monitor_audio(edid); 275 drm_connector_update_edid_property(connector, edid); 276 ret = drm_add_edid_modes(connector, edid); 277 kfree(edid); 278 279 return ret; 280} 281 282static enum drm_mode_status 283zx_hdmi_connector_mode_valid(struct drm_connector *connector, 284 struct drm_display_mode *mode) 285{ 286 return MODE_OK; 287} 288 289static struct drm_connector_helper_funcs zx_hdmi_connector_helper_funcs = { 290 .get_modes = zx_hdmi_connector_get_modes, 291 .mode_valid = zx_hdmi_connector_mode_valid, 292}; 293 294static enum drm_connector_status 295zx_hdmi_connector_detect(struct drm_connector *connector, bool force) 296{ 297 struct zx_hdmi *hdmi = to_zx_hdmi(connector); 298 299 return (hdmi_readb(hdmi, TPI_HPD_RSEN) & TPI_HPD_CONNECTION) ? 300 connector_status_connected : connector_status_disconnected; 301} 302 303static const struct drm_connector_funcs zx_hdmi_connector_funcs = { 304 .fill_modes = drm_helper_probe_single_connector_modes, 305 .detect = zx_hdmi_connector_detect, 306 .destroy = drm_connector_cleanup, 307 .reset = drm_atomic_helper_connector_reset, 308 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 309 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 310}; 311 312static int zx_hdmi_register(struct drm_device *drm, struct zx_hdmi *hdmi) 313{ 314 struct drm_encoder *encoder = &hdmi->encoder; 315 316 encoder->possible_crtcs = VOU_CRTC_MASK; 317 318 drm_encoder_init(drm, encoder, &zx_hdmi_encoder_funcs, 319 DRM_MODE_ENCODER_TMDS, NULL); 320 drm_encoder_helper_add(encoder, &zx_hdmi_encoder_helper_funcs); 321 322 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD; 323 324 drm_connector_init(drm, &hdmi->connector, &zx_hdmi_connector_funcs, 325 DRM_MODE_CONNECTOR_HDMIA); 326 drm_connector_helper_add(&hdmi->connector, 327 &zx_hdmi_connector_helper_funcs); 328 329 drm_connector_attach_encoder(&hdmi->connector, encoder); 330 331 return 0; 332} 333 334static irqreturn_t zx_hdmi_irq_thread(int irq, void *dev_id) 335{ 336 struct zx_hdmi *hdmi = dev_id; 337 338 drm_helper_hpd_irq_event(hdmi->connector.dev); 339 340 return IRQ_HANDLED; 341} 342 343static irqreturn_t zx_hdmi_irq_handler(int irq, void *dev_id) 344{ 345 struct zx_hdmi *hdmi = dev_id; 346 u8 lstat; 347 348 lstat = hdmi_readb(hdmi, L1_INTR_STAT); 349 350 /* Monitor detect/HPD interrupt */ 351 if (lstat & L1_INTR_STAT_INTR1) { 352 u8 stat; 353 354 stat = hdmi_readb(hdmi, INTR1_STAT); 355 hdmi_writeb(hdmi, INTR1_STAT, stat); 356 357 if (stat & INTR1_MONITOR_DETECT) 358 return IRQ_WAKE_THREAD; 359 } 360 361 return IRQ_NONE; 362} 363 364static int zx_hdmi_audio_startup(struct device *dev, void *data) 365{ 366 struct zx_hdmi *hdmi = dev_get_drvdata(dev); 367 struct drm_encoder *encoder = &hdmi->encoder; 368 369 vou_inf_hdmi_audio_sel(encoder->crtc, VOU_HDMI_AUD_SPDIF); 370 371 return 0; 372} 373 374static void zx_hdmi_audio_shutdown(struct device *dev, void *data) 375{ 376 struct zx_hdmi *hdmi = dev_get_drvdata(dev); 377 378 /* Disable audio input */ 379 hdmi_writeb_mask(hdmi, AUD_EN, AUD_IN_EN, 0); 380} 381 382static inline int zx_hdmi_audio_get_n(unsigned int fs) 383{ 384 unsigned int n; 385 386 if (fs && (fs % 44100) == 0) 387 n = 6272 * (fs / 44100); 388 else 389 n = fs * 128 / 1000; 390 391 return n; 392} 393 394static int zx_hdmi_audio_hw_params(struct device *dev, 395 void *data, 396 struct hdmi_codec_daifmt *daifmt, 397 struct hdmi_codec_params *params) 398{ 399 struct zx_hdmi *hdmi = dev_get_drvdata(dev); 400 struct hdmi_audio_infoframe *cea = &params->cea; 401 union hdmi_infoframe frame; 402 int n; 403 404 /* We only support spdif for now */ 405 if (daifmt->fmt != HDMI_SPDIF) { 406 DRM_DEV_ERROR(hdmi->dev, "invalid daifmt %d\n", daifmt->fmt); 407 return -EINVAL; 408 } 409 410 switch (params->sample_width) { 411 case 16: 412 hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, SPDIF_SAMPLE_SIZE_MASK, 413 SPDIF_SAMPLE_SIZE_16BIT); 414 break; 415 case 20: 416 hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, SPDIF_SAMPLE_SIZE_MASK, 417 SPDIF_SAMPLE_SIZE_20BIT); 418 break; 419 case 24: 420 hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, SPDIF_SAMPLE_SIZE_MASK, 421 SPDIF_SAMPLE_SIZE_24BIT); 422 break; 423 default: 424 DRM_DEV_ERROR(hdmi->dev, "invalid sample width %d\n", 425 params->sample_width); 426 return -EINVAL; 427 } 428 429 /* CTS is calculated by hardware, and we only need to take care of N */ 430 n = zx_hdmi_audio_get_n(params->sample_rate); 431 hdmi_writeb(hdmi, N_SVAL1, n & 0xff); 432 hdmi_writeb(hdmi, N_SVAL2, (n >> 8) & 0xff); 433 hdmi_writeb(hdmi, N_SVAL3, (n >> 16) & 0xf); 434 435 /* Enable spdif mode */ 436 hdmi_writeb_mask(hdmi, AUD_MODE, SPDIF_EN, SPDIF_EN); 437 438 /* Enable audio input */ 439 hdmi_writeb_mask(hdmi, AUD_EN, AUD_IN_EN, AUD_IN_EN); 440 441 memcpy(&frame.audio, cea, sizeof(*cea)); 442 443 return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_AUDIO); 444} 445 446static int zx_hdmi_audio_digital_mute(struct device *dev, void *data, 447 bool enable) 448{ 449 struct zx_hdmi *hdmi = dev_get_drvdata(dev); 450 451 if (enable) 452 hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, TPI_AUD_MUTE, 453 TPI_AUD_MUTE); 454 else 455 hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, TPI_AUD_MUTE, 0); 456 457 return 0; 458} 459 460static int zx_hdmi_audio_get_eld(struct device *dev, void *data, 461 uint8_t *buf, size_t len) 462{ 463 struct zx_hdmi *hdmi = dev_get_drvdata(dev); 464 struct drm_connector *connector = &hdmi->connector; 465 466 memcpy(buf, connector->eld, min(sizeof(connector->eld), len)); 467 468 return 0; 469} 470 471static const struct hdmi_codec_ops zx_hdmi_codec_ops = { 472 .audio_startup = zx_hdmi_audio_startup, 473 .hw_params = zx_hdmi_audio_hw_params, 474 .audio_shutdown = zx_hdmi_audio_shutdown, 475 .digital_mute = zx_hdmi_audio_digital_mute, 476 .get_eld = zx_hdmi_audio_get_eld, 477}; 478 479static struct hdmi_codec_pdata zx_hdmi_codec_pdata = { 480 .ops = &zx_hdmi_codec_ops, 481 .spdif = 1, 482}; 483 484static int zx_hdmi_audio_register(struct zx_hdmi *hdmi) 485{ 486 struct platform_device *pdev; 487 488 pdev = platform_device_register_data(hdmi->dev, HDMI_CODEC_DRV_NAME, 489 PLATFORM_DEVID_AUTO, 490 &zx_hdmi_codec_pdata, 491 sizeof(zx_hdmi_codec_pdata)); 492 if (IS_ERR(pdev)) 493 return PTR_ERR(pdev); 494 495 hdmi->audio_pdev = pdev; 496 497 return 0; 498} 499 500static int zx_hdmi_i2c_read(struct zx_hdmi *hdmi, struct i2c_msg *msg) 501{ 502 int len = msg->len; 503 u8 *buf = msg->buf; 504 int retry = 0; 505 int ret = 0; 506 507 /* Bits [9:8] of bytes */ 508 hdmi_writeb(hdmi, ZX_DDC_DIN_CNT2, (len >> 8) & 0xff); 509 /* Bits [7:0] of bytes */ 510 hdmi_writeb(hdmi, ZX_DDC_DIN_CNT1, len & 0xff); 511 512 /* Clear FIFO */ 513 hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK, DDC_CMD_CLEAR_FIFO); 514 515 /* Kick off the read */ 516 hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK, 517 DDC_CMD_SEQUENTIAL_READ); 518 519 while (len > 0) { 520 int cnt, i; 521 522 /* FIFO needs some time to get ready */ 523 usleep_range(500, 1000); 524 525 cnt = hdmi_readb(hdmi, ZX_DDC_DOUT_CNT) & DDC_DOUT_CNT_MASK; 526 if (cnt == 0) { 527 if (++retry > 5) { 528 DRM_DEV_ERROR(hdmi->dev, 529 "DDC FIFO read timed out!"); 530 return -ETIMEDOUT; 531 } 532 continue; 533 } 534 535 for (i = 0; i < cnt; i++) 536 *buf++ = hdmi_readb(hdmi, ZX_DDC_DATA); 537 len -= cnt; 538 } 539 540 return ret; 541} 542 543static int zx_hdmi_i2c_write(struct zx_hdmi *hdmi, struct i2c_msg *msg) 544{ 545 /* 546 * The DDC I2C adapter is only for reading EDID data, so we assume 547 * that the write to this adapter must be the EDID data offset. 548 */ 549 if ((msg->len != 1) || 550 ((msg->addr != DDC_ADDR) && (msg->addr != DDC_SEGMENT_ADDR))) 551 return -EINVAL; 552 553 if (msg->addr == DDC_SEGMENT_ADDR) 554 hdmi_writeb(hdmi, ZX_DDC_SEGM, msg->addr << 1); 555 else if (msg->addr == DDC_ADDR) 556 hdmi_writeb(hdmi, ZX_DDC_ADDR, msg->addr << 1); 557 558 hdmi_writeb(hdmi, ZX_DDC_OFFSET, msg->buf[0]); 559 560 return 0; 561} 562 563static int zx_hdmi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 564 int num) 565{ 566 struct zx_hdmi *hdmi = i2c_get_adapdata(adap); 567 struct zx_hdmi_i2c *ddc = hdmi->ddc; 568 int i, ret = 0; 569 570 mutex_lock(&ddc->lock); 571 572 /* Enable DDC master access */ 573 hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, HW_DDC_MASTER); 574 575 for (i = 0; i < num; i++) { 576 DRM_DEV_DEBUG(hdmi->dev, 577 "xfer: num: %d/%d, len: %d, flags: %#x\n", 578 i + 1, num, msgs[i].len, msgs[i].flags); 579 580 if (msgs[i].flags & I2C_M_RD) 581 ret = zx_hdmi_i2c_read(hdmi, &msgs[i]); 582 else 583 ret = zx_hdmi_i2c_write(hdmi, &msgs[i]); 584 585 if (ret < 0) 586 break; 587 } 588 589 if (!ret) 590 ret = num; 591 592 /* Disable DDC master access */ 593 hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, 0); 594 595 mutex_unlock(&ddc->lock); 596 597 return ret; 598} 599 600static u32 zx_hdmi_i2c_func(struct i2c_adapter *adapter) 601{ 602 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 603} 604 605static const struct i2c_algorithm zx_hdmi_algorithm = { 606 .master_xfer = zx_hdmi_i2c_xfer, 607 .functionality = zx_hdmi_i2c_func, 608}; 609 610static int zx_hdmi_ddc_register(struct zx_hdmi *hdmi) 611{ 612 struct i2c_adapter *adap; 613 struct zx_hdmi_i2c *ddc; 614 int ret; 615 616 ddc = devm_kzalloc(hdmi->dev, sizeof(*ddc), GFP_KERNEL); 617 if (!ddc) 618 return -ENOMEM; 619 620 hdmi->ddc = ddc; 621 mutex_init(&ddc->lock); 622 623 adap = &ddc->adap; 624 adap->owner = THIS_MODULE; 625 adap->class = I2C_CLASS_DDC; 626 adap->dev.parent = hdmi->dev; 627 adap->algo = &zx_hdmi_algorithm; 628 snprintf(adap->name, sizeof(adap->name), "zx hdmi i2c"); 629 630 ret = i2c_add_adapter(adap); 631 if (ret) { 632 DRM_DEV_ERROR(hdmi->dev, "failed to add I2C adapter: %d\n", 633 ret); 634 return ret; 635 } 636 637 i2c_set_adapdata(adap, hdmi); 638 639 return 0; 640} 641 642static int zx_hdmi_bind(struct device *dev, struct device *master, void *data) 643{ 644 struct platform_device *pdev = to_platform_device(dev); 645 struct drm_device *drm = data; 646 struct resource *res; 647 struct zx_hdmi *hdmi; 648 int irq; 649 int ret; 650 651 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); 652 if (!hdmi) 653 return -ENOMEM; 654 655 hdmi->dev = dev; 656 hdmi->drm = drm; 657 658 dev_set_drvdata(dev, hdmi); 659 660 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 661 hdmi->mmio = devm_ioremap_resource(dev, res); 662 if (IS_ERR(hdmi->mmio)) { 663 ret = PTR_ERR(hdmi->mmio); 664 DRM_DEV_ERROR(dev, "failed to remap hdmi region: %d\n", ret); 665 return ret; 666 } 667 668 irq = platform_get_irq(pdev, 0); 669 if (irq < 0) 670 return irq; 671 672 hdmi->cec_clk = devm_clk_get(hdmi->dev, "osc_cec"); 673 if (IS_ERR(hdmi->cec_clk)) { 674 ret = PTR_ERR(hdmi->cec_clk); 675 DRM_DEV_ERROR(dev, "failed to get cec_clk: %d\n", ret); 676 return ret; 677 } 678 679 hdmi->osc_clk = devm_clk_get(hdmi->dev, "osc_clk"); 680 if (IS_ERR(hdmi->osc_clk)) { 681 ret = PTR_ERR(hdmi->osc_clk); 682 DRM_DEV_ERROR(dev, "failed to get osc_clk: %d\n", ret); 683 return ret; 684 } 685 686 hdmi->xclk = devm_clk_get(hdmi->dev, "xclk"); 687 if (IS_ERR(hdmi->xclk)) { 688 ret = PTR_ERR(hdmi->xclk); 689 DRM_DEV_ERROR(dev, "failed to get xclk: %d\n", ret); 690 return ret; 691 } 692 693 ret = zx_hdmi_ddc_register(hdmi); 694 if (ret) { 695 DRM_DEV_ERROR(dev, "failed to register ddc: %d\n", ret); 696 return ret; 697 } 698 699 ret = zx_hdmi_audio_register(hdmi); 700 if (ret) { 701 DRM_DEV_ERROR(dev, "failed to register audio: %d\n", ret); 702 return ret; 703 } 704 705 ret = zx_hdmi_register(drm, hdmi); 706 if (ret) { 707 DRM_DEV_ERROR(dev, "failed to register hdmi: %d\n", ret); 708 return ret; 709 } 710 711 ret = devm_request_threaded_irq(dev, irq, zx_hdmi_irq_handler, 712 zx_hdmi_irq_thread, IRQF_SHARED, 713 dev_name(dev), hdmi); 714 if (ret) { 715 DRM_DEV_ERROR(dev, "failed to request threaded irq: %d\n", ret); 716 return ret; 717 } 718 719 return 0; 720} 721 722static void zx_hdmi_unbind(struct device *dev, struct device *master, 723 void *data) 724{ 725 struct zx_hdmi *hdmi = dev_get_drvdata(dev); 726 727 hdmi->connector.funcs->destroy(&hdmi->connector); 728 hdmi->encoder.funcs->destroy(&hdmi->encoder); 729 730 if (hdmi->audio_pdev) 731 platform_device_unregister(hdmi->audio_pdev); 732} 733 734static const struct component_ops zx_hdmi_component_ops = { 735 .bind = zx_hdmi_bind, 736 .unbind = zx_hdmi_unbind, 737}; 738 739static int zx_hdmi_probe(struct platform_device *pdev) 740{ 741 return component_add(&pdev->dev, &zx_hdmi_component_ops); 742} 743 744static int zx_hdmi_remove(struct platform_device *pdev) 745{ 746 component_del(&pdev->dev, &zx_hdmi_component_ops); 747 return 0; 748} 749 750static const struct of_device_id zx_hdmi_of_match[] = { 751 { .compatible = "zte,zx296718-hdmi", }, 752 { /* end */ }, 753}; 754MODULE_DEVICE_TABLE(of, zx_hdmi_of_match); 755 756struct platform_driver zx_hdmi_driver = { 757 .probe = zx_hdmi_probe, 758 .remove = zx_hdmi_remove, 759 .driver = { 760 .name = "zx-hdmi", 761 .of_match_table = zx_hdmi_of_match, 762 }, 763};