1 /* $OpenBSD: nxphdmi.c,v 1.6 2019/05/06 03:45:58 mlarkin Exp $ */ 2 /* 3 * Copyright (c) 2016 Ian Sutton <ians@openbsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 /* 29 * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org> 30 * All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 */ 53 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/device.h> 57 #include <sys/errno.h> 58 59 #include <dev/i2c/i2cvar.h> 60 #include <dev/videomode/videomode.h> 61 62 #include <dev/ofw/openfirm.h> 63 #include <dev/ofw/ofw_pinctrl.h> 64 65 #include <arch/armv7/omap/nxphdmivar.h> 66 67 /* TDA19988 registers */ 68 #define MKREG(page, addr) (((page) << 8) | (addr)) 69 70 #define REGPAGE(reg) (((reg) >> 8) & 0xff) 71 #define REGADDR(reg) ((reg) & 0xff) 72 73 #define TDA_VERSION MKREG(0x00, 0x00) 74 #define TDA_MAIN_CNTRL0 MKREG(0x00, 0x01) 75 #define MAIN_CNTRL0_SR (1 << 0) 76 #define TDA_VERSION_MSB MKREG(0x00, 0x02) 77 #define TDA_SOFTRESET MKREG(0x00, 0x0a) 78 #define SOFTRESET_I2C (1 << 1) 79 #define SOFTRESET_AUDIO (1 << 0) 80 #define TDA_DDC_CTRL MKREG(0x00, 0x0b) 81 #define DDC_ENABLE 0 82 #define TDA_CCLK MKREG(0x00, 0x0c) 83 #define CCLK_ENABLE 1 84 #define TDA_INT_FLAGS_2 MKREG(0x00, 0x11) 85 #define INT_FLAGS_2_EDID_BLK_RD (1 << 1) 86 87 #define TDA_VIP_CNTRL_0 MKREG(0x00, 0x20) 88 #define TDA_VIP_CNTRL_1 MKREG(0x00, 0x21) 89 #define TDA_VIP_CNTRL_2 MKREG(0x00, 0x22) 90 #define TDA_VIP_CNTRL_3 MKREG(0x00, 0x23) 91 #define VIP_CNTRL_3_SYNC_HS (2 << 4) 92 #define VIP_CNTRL_3_V_TGL (1 << 2) 93 #define VIP_CNTRL_3_H_TGL (1 << 1) 94 95 #define TDA_VIP_CNTRL_4 MKREG(0x00, 0x24) 96 #define VIP_CNTRL_4_BLANKIT_NDE (0 << 2) 97 #define VIP_CNTRL_4_BLANKIT_HS_VS (1 << 2) 98 #define VIP_CNTRL_4_BLANKIT_NHS_VS (2 << 2) 99 #define VIP_CNTRL_4_BLANKIT_HE_VE (3 << 2) 100 #define VIP_CNTRL_4_BLC_NONE (0 << 0) 101 #define VIP_CNTRL_4_BLC_RGB444 (1 << 0) 102 #define VIP_CNTRL_4_BLC_YUV444 (2 << 0) 103 #define VIP_CNTRL_4_BLC_YUV422 (3 << 0) 104 #define TDA_VIP_CNTRL_5 MKREG(0x00, 0x25) 105 #define VIP_CNTRL_5_SP_CNT(n) (((n) & 3) << 1) 106 #define TDA_MUX_VP_VIP_OUT MKREG(0x00, 0x27) 107 #define TDA_MAT_CONTRL MKREG(0x00, 0x80) 108 #define MAT_CONTRL_MAT_BP (1 << 2) 109 #define TDA_VIDFORMAT MKREG(0x00, 0xa0) 110 #define TDA_REFPIX_MSB MKREG(0x00, 0xa1) 111 #define TDA_REFPIX_LSB MKREG(0x00, 0xa2) 112 #define TDA_REFLINE_MSB MKREG(0x00, 0xa3) 113 #define TDA_REFLINE_LSB MKREG(0x00, 0xa4) 114 #define TDA_NPIX_MSB MKREG(0x00, 0xa5) 115 #define TDA_NPIX_LSB MKREG(0x00, 0xa6) 116 #define TDA_NLINE_MSB MKREG(0x00, 0xa7) 117 #define TDA_NLINE_LSB MKREG(0x00, 0xa8) 118 #define TDA_VS_LINE_STRT_1_MSB MKREG(0x00, 0xa9) 119 #define TDA_VS_LINE_STRT_1_LSB MKREG(0x00, 0xaa) 120 #define TDA_VS_PIX_STRT_1_MSB MKREG(0x00, 0xab) 121 #define TDA_VS_PIX_STRT_1_LSB MKREG(0x00, 0xac) 122 #define TDA_VS_LINE_END_1_MSB MKREG(0x00, 0xad) 123 #define TDA_VS_LINE_END_1_LSB MKREG(0x00, 0xae) 124 #define TDA_VS_PIX_END_1_MSB MKREG(0x00, 0xaf) 125 #define TDA_VS_PIX_END_1_LSB MKREG(0x00, 0xb0) 126 #define TDA_VS_LINE_STRT_2_MSB MKREG(0x00, 0xb1) 127 #define TDA_VS_LINE_STRT_2_LSB MKREG(0x00, 0xb2) 128 #define TDA_VS_PIX_STRT_2_MSB MKREG(0x00, 0xb3) 129 #define TDA_VS_PIX_STRT_2_LSB MKREG(0x00, 0xb4) 130 #define TDA_VS_LINE_END_2_MSB MKREG(0x00, 0xb5) 131 #define TDA_VS_LINE_END_2_LSB MKREG(0x00, 0xb6) 132 #define TDA_VS_PIX_END_2_MSB MKREG(0x00, 0xb7) 133 #define TDA_VS_PIX_END_2_LSB MKREG(0x00, 0xb8) 134 #define TDA_HS_PIX_START_MSB MKREG(0x00, 0xb9) 135 #define TDA_HS_PIX_START_LSB MKREG(0x00, 0xba) 136 #define TDA_HS_PIX_STOP_MSB MKREG(0x00, 0xbb) 137 #define TDA_HS_PIX_STOP_LSB MKREG(0x00, 0xbc) 138 #define TDA_VWIN_START_1_MSB MKREG(0x00, 0xbd) 139 #define TDA_VWIN_START_1_LSB MKREG(0x00, 0xbe) 140 #define TDA_VWIN_END_1_MSB MKREG(0x00, 0xbf) 141 #define TDA_VWIN_END_1_LSB MKREG(0x00, 0xc0) 142 #define TDA_VWIN_START_2_MSB MKREG(0x00, 0xc1) 143 #define TDA_VWIN_START_2_LSB MKREG(0x00, 0xc2) 144 #define TDA_VWIN_END_2_MSB MKREG(0x00, 0xc3) 145 #define TDA_VWIN_END_2_LSB MKREG(0x00, 0xc4) 146 #define TDA_DE_START_MSB MKREG(0x00, 0xc5) 147 #define TDA_DE_START_LSB MKREG(0x00, 0xc6) 148 #define TDA_DE_STOP_MSB MKREG(0x00, 0xc7) 149 #define TDA_DE_STOP_LSB MKREG(0x00, 0xc8) 150 151 #define TDA_TBG_CNTRL_0 MKREG(0x00, 0xca) 152 #define TBG_CNTRL_0_SYNC_ONCE (1 << 7) 153 #define TBG_CNTRL_0_SYNC_MTHD (1 << 6) 154 155 #define TDA_TBG_CNTRL_1 MKREG(0x00, 0xcb) 156 #define TBG_CNTRL_1_DWIN_DIS (1 << 6) 157 #define TBG_CNTRL_1_TGL_EN (1 << 2) 158 #define TBG_CNTRL_1_V_TGL (1 << 1) 159 #define TBG_CNTRL_1_H_TGL (1 << 0) 160 161 #define TDA_HVF_CNTRL_0 MKREG(0x00, 0xe4) 162 #define HVF_CNTRL_0_PREFIL_NONE (0 << 2) 163 #define HVF_CNTRL_0_INTPOL_BYPASS (0 << 0) 164 #define TDA_HVF_CNTRL_1 MKREG(0x00, 0xe5) 165 #define HVF_CNTRL_1_VQR(x) (((x) & 3) << 2) 166 #define HVF_CNTRL_1_VQR_FULL HVF_CNTRL_1_VQR(0) 167 #define TDA_ENABLE_SPACE MKREG(0x00, 0xd6) 168 #define TDA_RPT_CNTRL MKREG(0x00, 0xf0) 169 170 #define TDA_PLL_SERIAL_1 MKREG(0x02, 0x00) 171 #define PLL_SERIAL_1_SRL_MAN_IP (1 << 6) 172 #define TDA_PLL_SERIAL_2 MKREG(0x02, 0x01) 173 #define PLL_SERIAL_2_SRL_PR(x) (((x) & 0xf) << 4) 174 #define PLL_SERIAL_2_SRL_NOSC(x) (((x) & 0x3) << 0) 175 #define TDA_PLL_SERIAL_3 MKREG(0x02, 0x02) 176 #define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4) 177 #define PLL_SERIAL_3_SRL_DE (1 << 2) 178 #define PLL_SERIAL_3_SRL_CCIR (1 << 0) 179 #define TDA_SERIALIZER MKREG(0x02, 0x03) 180 #define TDA_BUFFER_OUT MKREG(0x02, 0x04) 181 #define TDA_PLL_SCG1 MKREG(0x02, 0x05) 182 #define TDA_PLL_SCG2 MKREG(0x02, 0x06) 183 #define TDA_PLL_SCGN1 MKREG(0x02, 0x07) 184 #define TDA_PLL_SCGN2 MKREG(0x02, 0x08) 185 #define TDA_PLL_SCGR1 MKREG(0x02, 0x09) 186 #define TDA_PLL_SCGR2 MKREG(0x02, 0x0a) 187 188 #define TDA_SEL_CLK MKREG(0x02, 0x11) 189 #define SEL_CLK_ENA_SC_CLK (1 << 3) 190 #define SEL_CLK_SEL_VRF_CLK(x) (((x) & 3) << 1) 191 #define SEL_CLK_SEL_CLK1 (1 << 0) 192 #define TDA_ANA_GENERAL MKREG(0x02, 0x12) 193 194 #define TDA_EDID_DATA0 MKREG(0x09, 0x00) 195 #define TDA_EDID_CTRL MKREG(0x09, 0xfa) 196 #define TDA_DDC_ADDR MKREG(0x09, 0xfb) 197 #define TDA_DDC_OFFS MKREG(0x09, 0xfc) 198 #define TDA_DDC_SEGM_ADDR MKREG(0x09, 0xfd) 199 #define TDA_DDC_SEGM MKREG(0x09, 0xfe) 200 201 #define TDA_IF_VSP MKREG(0x10, 0x20) 202 #define TDA_IF_AVI MKREG(0x10, 0x40) 203 #define TDA_IF_SPD MKREG(0x10, 0x60) 204 #define TDA_IF_AUD MKREG(0x10, 0x80) 205 #define TDA_IF_MPS MKREG(0x10, 0xa0) 206 207 #define TDA_ENC_CNTRL MKREG(0x11, 0x0d) 208 #define ENC_CNTRL_DVI_MODE (0 << 2) 209 #define ENC_CNTRL_HDMI_MODE (1 << 2) 210 #define TDA_DIP_IF_FLAGS MKREG(0x11, 0x0f) 211 #define DIP_IF_FLAGS_IF5 (1 << 5) 212 #define DIP_IF_FLAGS_IF4 (1 << 4) 213 #define DIP_IF_FLAGS_IF3 (1 << 3) 214 #define DIP_IF_FLAGS_IF2 (1 << 2) /* AVI IF on page 10h */ 215 #define DIP_IF_FLAGS_IF1 (1 << 1) 216 217 #define TDA_TX3 MKREG(0x12, 0x9a) 218 #define TDA_TX4 MKREG(0x12, 0x9b) 219 #define TX4_PD_RAM (1 << 1) 220 #define TDA_HDCP_TX33 MKREG(0x12, 0xb8) 221 #define HDCP_TX33_HDMI (1 << 1) 222 223 #define TDA_CURPAGE_ADDR 0xff 224 225 #define TDA_CEC_ENAMODS 0xff 226 #define ENAMODS_RXSENS (1 << 2) 227 #define ENAMODS_HDMI (1 << 1) 228 #define TDA_CEC_FRO_IM_CLK_CTRL 0xfb 229 #define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7) 230 #define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1) 231 232 /* EDID reading */ 233 #define EDID_LENGTH 0x80 234 #define MAX_READ_ATTEMPTS 100 235 236 /* EDID fields */ 237 #define EDID_MODES0 35 238 #define EDID_MODES1 36 239 #define EDID_TIMING_START 38 240 #define EDID_TIMING_END 54 241 #define EDID_TIMING_X(v) (((v) + 31) * 8) 242 #define EDID_FREQ(v) (((v) & 0x3f) + 60) 243 #define EDID_RATIO(v) (((v) >> 6) & 0x3) 244 #define EDID_RATIO_10x16 0 245 #define EDID_RATIO_3x4 1 246 #define EDID_RATIO_4x5 2 247 #define EDID_RATIO_9x16 3 248 249 /* NXP TDA19988 slave addrs. */ 250 #define TDA_HDMI 0x70 251 #define TDA_CEC 0x34 252 253 /* debug/etc macros */ 254 #define DEVNAME(s) ((s)->sc_dev.dv_xname) 255 #ifdef NXPTDA_DEBUG 256 int nxphdmi_debug = 1; 257 #define DPRINTF(n,s) do { if ((n) <= nxphdmi_debug) printf s; } while (0) 258 #else 259 #define DPRINTF(n,s) do {} while (0) 260 #endif 261 262 struct nxphdmi_softc { 263 struct device sc_dev; 264 i2c_tag_t sc_tag; 265 i2c_addr_t sc_addr; 266 267 uint8_t sc_curpage; 268 uint8_t sc_edid[EDID_LENGTH]; 269 }; 270 271 int nxphdmi_match(struct device *, void *, void *); 272 void nxphdmi_attach(struct device *, struct device *, void *); 273 274 int nxphdmi_cec_read(struct nxphdmi_softc *, uint8_t, uint8_t *); 275 int nxphdmi_cec_write(struct nxphdmi_softc *, uint8_t, uint8_t); 276 int nxphdmi_read(struct nxphdmi_softc *, uint16_t, uint8_t *); 277 int nxphdmi_write(struct nxphdmi_softc *, uint16_t, uint8_t); 278 int nxphdmi_write2(struct nxphdmi_softc *, uint16_t, uint16_t); 279 int nxphdmi_set(struct nxphdmi_softc *, uint16_t, uint8_t); 280 int nxphdmi_clear(struct nxphdmi_softc *, uint16_t, uint8_t); 281 int nxphdmi_set_page(struct nxphdmi_softc *, uint8_t); 282 int nxphdmi_read_edid(struct nxphdmi_softc *); 283 int nxphdmi_reset(struct nxphdmi_softc *); 284 int nxphdmi_init_encoder(struct nxphdmi_softc *, struct videomode *); 285 286 int nxphdmi_get_edid(uint8_t *, int); 287 int nxphdmi_set_videomode(struct videomode *); 288 289 struct cfattach nxphdmi_ca = { 290 sizeof(struct nxphdmi_softc), nxphdmi_match, nxphdmi_attach 291 }; 292 293 struct cfdriver nxphdmi_cd = { 294 NULL, "nxphdmi", DV_DULL 295 }; 296 297 int 298 nxphdmi_match(struct device *parent, void *match, void *aux) 299 { 300 struct i2c_attach_args *ia = aux; 301 302 if (strcmp(ia->ia_name, "nxp,tda998x") == 0) 303 return 1; 304 305 return 0; 306 } 307 308 void 309 nxphdmi_attach(struct device *parent, struct device *self, void *aux) 310 { 311 struct nxphdmi_softc *sc = (struct nxphdmi_softc *)self; 312 struct i2c_attach_args *ia = aux; 313 uint8_t data = 0; 314 uint16_t version = 0; 315 int res = 0, node = *(int *)(ia->ia_cookie); 316 317 sc->sc_tag = ia->ia_tag; 318 sc->sc_addr = ia->ia_addr; 319 sc->sc_curpage = 0xff; 320 321 if (!node) { 322 printf(": not configured\n"); 323 return; 324 } else if ((pinctrl_byname(node, "default") == -1)) { 325 printf(": not configured\n"); 326 return; 327 } 328 329 iic_acquire_bus(sc->sc_tag, 0); 330 331 DPRINTF(3,("\n")); 332 333 /* enable HDMI core */ 334 nxphdmi_cec_write(sc, TDA_CEC_ENAMODS, ENAMODS_RXSENS | ENAMODS_HDMI); 335 delay(1000); 336 337 if (!(nxphdmi_reset(sc))) 338 DPRINTF(3,("%s: software reset OK\n", DEVNAME(sc))); 339 else 340 DPRINTF(3,("%s: software reset failed!\n", DEVNAME(sc))); 341 342 /* PLL registers common configuration */ 343 nxphdmi_write(sc, TDA_PLL_SERIAL_1, 0x00); 344 nxphdmi_write(sc, TDA_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1)); 345 nxphdmi_write(sc, TDA_PLL_SERIAL_3, 0x00); 346 nxphdmi_write(sc, TDA_SERIALIZER, 0x00); 347 nxphdmi_write(sc, TDA_BUFFER_OUT, 0x00); 348 nxphdmi_write(sc, TDA_PLL_SCG1, 0x00); 349 nxphdmi_write(sc, TDA_SEL_CLK, SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK); 350 nxphdmi_write(sc, TDA_PLL_SCGN1, 0xfa); 351 nxphdmi_write(sc, TDA_PLL_SCGN2, 0x00); 352 nxphdmi_write(sc, TDA_PLL_SCGR1, 0x5b); 353 nxphdmi_write(sc, TDA_PLL_SCGR2, 0x00); 354 nxphdmi_write(sc, TDA_PLL_SCG2, 0x10); 355 356 /* Write the default value MUX register */ 357 nxphdmi_write(sc, TDA_MUX_VP_VIP_OUT, 0x24); 358 359 res |= nxphdmi_read(sc, TDA_VERSION, &data); 360 version |= data; 361 res |= nxphdmi_read(sc, TDA_VERSION_MSB, &data); 362 version |= (data << 8); 363 version &= ~0x30; 364 365 if (!res) { 366 DPRINTF(3,("%s: ", DEVNAME(sc))); 367 printf(": rev 0x%04x\n", version); 368 } else { 369 DPRINTF(3,("%s: ", DEVNAME(sc))); 370 printf(": failed to enable HDMI core, exiting...\n"); 371 iic_release_bus(sc->sc_tag, 0); 372 return; 373 } 374 375 nxphdmi_write(sc, TDA_DDC_CTRL, DDC_ENABLE); 376 nxphdmi_write(sc, TDA_TX3, 39); 377 378 nxphdmi_cec_write(sc, TDA_CEC_FRO_IM_CLK_CTRL, 379 CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL); 380 381 if (nxphdmi_read_edid(sc)) { 382 DPRINTF(3,("%s: failed to read EDID bits, exiting!\n", 383 DEVNAME(sc))); 384 return; 385 } 386 387 /* Default values for RGB 4:4:4 mapping */ 388 nxphdmi_write(sc, TDA_VIP_CNTRL_0, 0x23); 389 nxphdmi_write(sc, TDA_VIP_CNTRL_1, 0x01); 390 nxphdmi_write(sc, TDA_VIP_CNTRL_2, 0x45); 391 392 iic_release_bus(sc->sc_tag, 0); 393 } 394 395 int 396 nxphdmi_cec_read(struct nxphdmi_softc *sc, uint8_t addr, uint8_t *buf) 397 { 398 int ret = 0; 399 400 if ((ret |= iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, TDA_CEC, 401 &addr, 1, NULL, 0, 0))) { 402 DPRINTF(3,("%s: (CEC) failed to read addr 0x%02x, errno %d\n", 403 DEVNAME(sc), addr, ret)); 404 return ret; 405 } 406 407 DPRINTF(3,("%s: (CEC) read 0x%02x from 0x%02x\n", DEVNAME(sc), *buf, 408 addr)); 409 410 return ret; 411 } 412 413 int 414 nxphdmi_cec_write(struct nxphdmi_softc *sc, uint8_t addr, uint8_t val) 415 { 416 int ret = 0; 417 uint8_t sendbuf[] = { addr, val }; 418 419 if ((ret |= iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, TDA_CEC, 420 &sendbuf, 2, NULL, 0, 0))) { 421 DPRINTF(3,( 422 "%s: (CEC) failed to write 0x%02x to 0x%02x, errno %d\n", 423 DEVNAME(sc), val, addr, ret)); 424 return ret; 425 } 426 427 DPRINTF(3,("%s: (CEC) wrote 0x%02x to 0x%02x\n", DEVNAME(sc), val, 428 addr)); 429 430 return ret; 431 } 432 433 int 434 nxphdmi_read(struct nxphdmi_softc *sc, uint16_t reg, uint8_t *buf) 435 { 436 int ret = 0; 437 438 nxphdmi_set_page(sc, REGPAGE(reg)); 439 440 if ((ret = iic_smbus_read_byte(sc->sc_tag, TDA_HDMI, REGADDR(reg), 441 buf, 0))) { 442 DPRINTF(3,( 443 "%s: failed to read addr 0x%02x on page 0x%02x, errno %d\n", 444 DEVNAME(sc), REGADDR(reg), REGPAGE(reg), ret)); 445 return ret; 446 } 447 448 DPRINTF(3,("%s: read 0x%02x from 0x%02x on page 0x%02x\n", 449 DEVNAME(sc), *buf, REGADDR(reg), REGPAGE(reg))); 450 451 return ret; 452 } 453 454 int 455 nxphdmi_write(struct nxphdmi_softc *sc, uint16_t reg, uint8_t val) 456 { 457 int ret = 0; 458 uint8_t sendbuf[] = { REGADDR(reg), val }; 459 460 nxphdmi_set_page(sc, REGPAGE(reg)); 461 462 if ((ret = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, TDA_HDMI, 463 &sendbuf, 2, NULL, 0, 0))) { 464 DPRINTF(3,( 465 "%s: failed to write 0x%02x to 0x%02x on page 0x%02x, errno %d\n", 466 DEVNAME(sc), val, REGADDR(reg), REGPAGE(reg), ret)); 467 return ret; 468 } 469 470 DPRINTF(3,("%s: wrote 0x%02x to 0x%02x on page 0x%02x\n", 471 DEVNAME(sc), val, REGADDR(reg), REGPAGE(reg))); 472 473 return ret; 474 } 475 476 int 477 nxphdmi_write2(struct nxphdmi_softc *sc, uint16_t reg, uint16_t val) 478 { 479 int ret = 0; 480 uint8_t sendbuf[] = { REGADDR(reg), val >> 8, val & 0xff }; 481 482 nxphdmi_set_page(sc, REGPAGE(reg)); 483 484 if ((ret = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, TDA_HDMI, 485 &sendbuf, 3, NULL, 0, 0))) { 486 DPRINTF(3,( 487 "%s: failed to write 0x%04x to 0x%02x on page 0x%02x, errno %d\n", 488 DEVNAME(sc), val, REGADDR(reg), REGPAGE(reg), ret)); 489 return ret; 490 } 491 492 DPRINTF(3,("%s: wrote 0x%04x to 0x%02x on page 0x%02x\n", 493 DEVNAME(sc), val, REGADDR(reg), REGPAGE(reg))); 494 495 return ret; 496 497 } 498 499 int 500 nxphdmi_set(struct nxphdmi_softc *sc, uint16_t reg, uint8_t bits) 501 { 502 int ret = 0; 503 uint8_t buf; 504 505 ret |= nxphdmi_read(sc, reg, &buf); 506 buf |= bits; 507 ret |= nxphdmi_write(sc, reg, buf); 508 509 return ret; 510 } 511 512 int 513 nxphdmi_clear(struct nxphdmi_softc *sc, uint16_t reg, uint8_t bits) 514 { 515 int ret = 0; 516 uint8_t buf; 517 518 ret |= nxphdmi_read(sc, reg, &buf); 519 buf &= ~bits; 520 ret |= nxphdmi_write(sc, reg, buf); 521 522 return ret; 523 } 524 525 int 526 nxphdmi_set_page(struct nxphdmi_softc *sc, uint8_t page) 527 { 528 int ret = 0; 529 uint8_t sendbuf[] = { TDA_CURPAGE_ADDR, page }; 530 531 if (sc->sc_curpage == page) 532 return ret; 533 534 if ((ret = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, TDA_HDMI, 535 &sendbuf, sizeof(sendbuf), NULL, 0, 0))) { 536 DPRINTF(3,("%s: failed to set memory page 0x%02x, errno %d\n", 537 DEVNAME(sc), 538 page, ret)); 539 return ret; 540 } 541 542 sc->sc_curpage = page; 543 DPRINTF(3,("%s: set page to 0x%02x\n", DEVNAME(sc), page)); 544 545 return ret; 546 } 547 548 int 549 nxphdmi_read_edid(struct nxphdmi_softc *sc) 550 { 551 int i = 0, ret = 0; 552 uint8_t reg; 553 554 nxphdmi_set(sc, TDA_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); 555 556 /* Block 0 */ 557 nxphdmi_write(sc, TDA_DDC_ADDR, 0xa0); 558 nxphdmi_write(sc, TDA_DDC_OFFS, 0x00); 559 nxphdmi_write(sc, TDA_DDC_SEGM_ADDR, 0x60); 560 nxphdmi_write(sc, TDA_DDC_SEGM, 0x00); 561 562 nxphdmi_write(sc, TDA_EDID_CTRL, 1); 563 nxphdmi_write(sc, TDA_EDID_CTRL, 0); 564 565 for (; i < MAX_READ_ATTEMPTS; i++) { 566 nxphdmi_read(sc, TDA_INT_FLAGS_2, ®); 567 if (reg & INT_FLAGS_2_EDID_BLK_RD) { 568 DPRINTF(3,("%s: EDID-ready IRQ fired\n", DEVNAME(sc))); 569 break; 570 } 571 } 572 573 if (i == MAX_READ_ATTEMPTS) { 574 printf("%s: no display detected\n", DEVNAME(sc)); 575 ret = ENXIO; 576 return ret; 577 } 578 579 nxphdmi_set_page(sc, 0x09); 580 581 reg = 0x00; 582 DPRINTF(1,("%s: ------------- EDID -------------", DEVNAME(sc))); 583 for (i = 0; i < EDID_LENGTH; i++) { 584 iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, TDA_HDMI, ®, 1, 585 &sc->sc_edid[i], 1, 0); 586 if (!(i % 16)) 587 DPRINTF(1,("\n%s: ", DEVNAME(sc))); 588 DPRINTF(1,("%02x", sc->sc_edid[i])); 589 reg++; 590 } 591 DPRINTF(1,("\n%s: --------------------------------\n", DEVNAME(sc))); 592 593 nxphdmi_clear(sc, TDA_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); 594 nxphdmi_set(sc, TDA_TX4, TX4_PD_RAM); 595 596 return ret; 597 } 598 599 int 600 nxphdmi_reset(struct nxphdmi_softc *sc) 601 { 602 int ret = 0; 603 604 /* reset core */ 605 ret |= nxphdmi_set(sc, TDA_SOFTRESET, 3); 606 delay(100); 607 ret |= nxphdmi_clear(sc, TDA_SOFTRESET, 3); 608 delay(100); 609 610 /* reset transmitter */ 611 ret |= nxphdmi_set(sc, TDA_MAIN_CNTRL0, MAIN_CNTRL0_SR); 612 ret |= nxphdmi_clear(sc, TDA_MAIN_CNTRL0, MAIN_CNTRL0_SR); 613 614 return ret; 615 } 616 617 int 618 nxphdmi_init_encoder(struct nxphdmi_softc *sc, struct videomode *mode) 619 { 620 int ret = 0; 621 622 uint16_t ref_pix, ref_line, n_pix, n_line; 623 uint16_t hs_pix_start, hs_pix_stop; 624 uint16_t vs1_pix_start, vs1_pix_stop; 625 uint16_t vs1_line_start, vs1_line_end; 626 uint16_t vs2_pix_start, vs2_pix_stop; 627 uint16_t vs2_line_start, vs2_line_end; 628 uint16_t vwin1_line_start, vwin1_line_end; 629 uint16_t vwin2_line_start, vwin2_line_end; 630 uint16_t de_start, de_stop; 631 uint8_t reg, div; 632 633 n_pix = mode->htotal; 634 n_line = mode->vtotal; 635 636 hs_pix_stop = mode->hsync_end - mode->hdisplay; 637 hs_pix_start = mode->hsync_start - mode->hdisplay; 638 639 de_stop = mode->htotal; 640 de_start = mode->htotal - mode->hdisplay; 641 ref_pix = hs_pix_start + 3; 642 643 if (mode->flags & VID_HSKEW) 644 ref_pix += mode->hsync_end - mode->hsync_start; 645 646 if ((mode->flags & VID_INTERLACE) == 0) { 647 ref_line = 1 + mode->vsync_start - mode->vdisplay; 648 vwin1_line_start = mode->vtotal - mode->vdisplay - 1; 649 vwin1_line_end = vwin1_line_start + mode->vdisplay; 650 651 vs1_pix_start = vs1_pix_stop = hs_pix_start; 652 vs1_line_start = mode->vsync_start - mode->vdisplay; 653 vs1_line_end = vs1_line_start + 654 mode->vsync_end - mode->vsync_start; 655 656 vwin2_line_start = vwin2_line_end = 0; 657 vs2_pix_start = vs2_pix_stop = 0; 658 vs2_line_start = vs2_line_end = 0; 659 } else { 660 ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2; 661 vwin1_line_start = (mode->vtotal - mode->vdisplay)/2; 662 vwin1_line_end = vwin1_line_start + mode->vdisplay/2; 663 664 vs1_pix_start = vs1_pix_stop = hs_pix_start; 665 vs1_line_start = (mode->vsync_start - mode->vdisplay)/2; 666 vs1_line_end = vs1_line_start + 667 (mode->vsync_end - mode->vsync_start)/2; 668 669 vwin2_line_start = vwin1_line_start + mode->vtotal/2; 670 vwin2_line_end = vwin2_line_start + mode->vdisplay/2; 671 672 vs2_pix_start = vs2_pix_stop = hs_pix_start + mode->htotal/2; 673 vs2_line_start = vs1_line_start + mode->vtotal/2 ; 674 vs2_line_end = vs2_line_start + 675 (mode->vsync_end - mode->vsync_start)/2; 676 } 677 678 div = 148500 / mode->dot_clock; 679 if (div != 0) { 680 div--; 681 if (div > 3) 682 div = 3; 683 } 684 685 /* set HDMI HDCP mode off */ 686 nxphdmi_set(sc, TDA_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS); 687 nxphdmi_clear(sc, TDA_HDCP_TX33, HDCP_TX33_HDMI); 688 nxphdmi_write(sc, TDA_ENC_CNTRL, ENC_CNTRL_DVI_MODE); 689 690 /* no pre-filter or interpolator */ 691 nxphdmi_write(sc, TDA_HVF_CNTRL_0, 692 HVF_CNTRL_0_INTPOL_BYPASS | HVF_CNTRL_0_PREFIL_NONE); 693 nxphdmi_write(sc, TDA_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0)); 694 nxphdmi_write(sc, TDA_VIP_CNTRL_4, 695 VIP_CNTRL_4_BLANKIT_NDE | VIP_CNTRL_4_BLC_NONE); 696 697 nxphdmi_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR); 698 nxphdmi_clear(sc, TDA_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IP); 699 nxphdmi_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE); 700 nxphdmi_write(sc, TDA_SERIALIZER, 0); 701 nxphdmi_write(sc, TDA_HVF_CNTRL_1, HVF_CNTRL_1_VQR_FULL); 702 703 nxphdmi_write(sc, TDA_RPT_CNTRL, 0); 704 nxphdmi_write(sc, TDA_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) | 705 SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK); 706 707 nxphdmi_write(sc, TDA_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) | 708 PLL_SERIAL_2_SRL_PR(0)); 709 710 nxphdmi_set(sc, TDA_MAT_CONTRL, MAT_CONTRL_MAT_BP); 711 712 nxphdmi_write(sc, TDA_ANA_GENERAL, 0x09); 713 714 nxphdmi_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD); 715 716 /* 717 * Sync on rising HSYNC/VSYNC 718 */ 719 reg = VIP_CNTRL_3_SYNC_HS; 720 if (mode->flags & VID_NHSYNC) 721 reg |= VIP_CNTRL_3_H_TGL; 722 if (mode->flags & VID_NVSYNC) 723 reg |= VIP_CNTRL_3_V_TGL; 724 nxphdmi_write(sc, TDA_VIP_CNTRL_3, reg); 725 726 reg = TBG_CNTRL_1_TGL_EN; 727 if (mode->flags & VID_NHSYNC) 728 reg |= TBG_CNTRL_1_H_TGL; 729 if (mode->flags & VID_NVSYNC) 730 reg |= TBG_CNTRL_1_V_TGL; 731 nxphdmi_write(sc, TDA_TBG_CNTRL_1, reg); 732 733 /* Program timing */ 734 nxphdmi_write(sc, TDA_VIDFORMAT, 0x00); 735 736 nxphdmi_write2(sc, TDA_REFPIX_MSB, ref_pix); 737 nxphdmi_write2(sc, TDA_REFLINE_MSB, ref_line); 738 nxphdmi_write2(sc, TDA_NPIX_MSB, n_pix); 739 nxphdmi_write2(sc, TDA_NLINE_MSB, n_line); 740 741 nxphdmi_write2(sc, TDA_VS_LINE_STRT_1_MSB, vs1_line_start); 742 nxphdmi_write2(sc, TDA_VS_PIX_STRT_1_MSB, vs1_pix_start); 743 nxphdmi_write2(sc, TDA_VS_LINE_END_1_MSB, vs1_line_end); 744 nxphdmi_write2(sc, TDA_VS_PIX_END_1_MSB, vs1_pix_stop); 745 nxphdmi_write2(sc, TDA_VS_LINE_STRT_2_MSB, vs2_line_start); 746 nxphdmi_write2(sc, TDA_VS_PIX_STRT_2_MSB, vs2_pix_start); 747 nxphdmi_write2(sc, TDA_VS_LINE_END_2_MSB, vs2_line_end); 748 nxphdmi_write2(sc, TDA_VS_PIX_END_2_MSB, vs2_pix_stop); 749 nxphdmi_write2(sc, TDA_HS_PIX_START_MSB, hs_pix_start); 750 nxphdmi_write2(sc, TDA_HS_PIX_STOP_MSB, hs_pix_stop); 751 nxphdmi_write2(sc, TDA_VWIN_START_1_MSB, vwin1_line_start); 752 nxphdmi_write2(sc, TDA_VWIN_END_1_MSB, vwin1_line_end); 753 nxphdmi_write2(sc, TDA_VWIN_START_2_MSB, vwin2_line_start); 754 nxphdmi_write2(sc, TDA_VWIN_END_2_MSB, vwin2_line_end); 755 nxphdmi_write2(sc, TDA_DE_START_MSB, de_start); 756 nxphdmi_write2(sc, TDA_DE_STOP_MSB, de_stop); 757 758 nxphdmi_write(sc, TDA_ENABLE_SPACE, 0x00); 759 760 /* must be last register set */ 761 nxphdmi_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE); 762 763 return ret; 764 } 765 766 int 767 nxphdmi_get_edid(uint8_t *buf, int buflen) 768 { 769 int ret = 0, i; 770 struct nxphdmi_softc *sc = nxphdmi_cd.cd_devs[0]; 771 772 if (buflen < EDID_LENGTH) 773 return -1; 774 775 for (i = 0; i < EDID_LENGTH; i++) 776 buf[i] = sc->sc_edid[i]; 777 778 return ret; 779 } 780 781 int 782 nxphdmi_set_videomode(struct videomode *mode) 783 { 784 int ret = 0; 785 struct nxphdmi_softc *sc = nxphdmi_cd.cd_devs[0]; 786 787 ret = nxphdmi_init_encoder(sc, mode); 788 789 return ret; 790 } 791