1 1.8 chs /* $NetBSD: au8522.c,v 1.8 2017/06/01 02:45:10 chs Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill /*- 4 1.1 jmcneill * Copyright (c) 2010 Jared D. McNeill <jmcneill (at) invisible.ca> 5 1.1 jmcneill * All rights reserved. 6 1.1 jmcneill * 7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 8 1.1 jmcneill * modification, are permitted provided that the following conditions 9 1.1 jmcneill * are met: 10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 11 1.1 jmcneill * notice, this list of conditions and the following disclaimer. 12 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the 14 1.1 jmcneill * documentation and/or other materials provided with the distribution. 15 1.1 jmcneill * 16 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 jmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 jmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 jmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 jmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 jmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 jmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 jmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 jmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 jmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 jmcneill * POSSIBILITY OF SUCH DAMAGE. 27 1.1 jmcneill */ 28 1.1 jmcneill 29 1.1 jmcneill /* 30 1.1 jmcneill * Auvitek AU8522 31 1.1 jmcneill */ 32 1.1 jmcneill 33 1.1 jmcneill #include <sys/cdefs.h> 34 1.8 chs __KERNEL_RCSID(0, "$NetBSD: au8522.c,v 1.8 2017/06/01 02:45:10 chs Exp $"); 35 1.1 jmcneill 36 1.1 jmcneill #include <sys/param.h> 37 1.1 jmcneill #include <sys/systm.h> 38 1.1 jmcneill #include <sys/device.h> 39 1.1 jmcneill #include <sys/conf.h> 40 1.1 jmcneill #include <sys/bus.h> 41 1.1 jmcneill #include <sys/kmem.h> 42 1.1 jmcneill #include <sys/module.h> 43 1.1 jmcneill 44 1.4 jmcneill #include <dev/dtv/dtvio.h> 45 1.4 jmcneill 46 1.1 jmcneill #include <dev/i2c/i2cvar.h> 47 1.1 jmcneill 48 1.1 jmcneill #include <dev/i2c/au8522reg.h> 49 1.1 jmcneill #include <dev/i2c/au8522var.h> 50 1.4 jmcneill #include <dev/i2c/au8522mod.h> 51 1.1 jmcneill 52 1.1 jmcneill static int au8522_reset(struct au8522 *); 53 1.1 jmcneill static int au8522_read_1(struct au8522 *, uint16_t, uint8_t *); 54 1.1 jmcneill static int au8522_write_1(struct au8522 *, uint16_t, uint8_t); 55 1.1 jmcneill static int au8522_set_vinput(struct au8522 *, au8522_vinput_t); 56 1.1 jmcneill static int au8522_set_ainput(struct au8522 *, au8522_ainput_t); 57 1.1 jmcneill static void au8522_set_common(struct au8522 *, au8522_vinput_t); 58 1.1 jmcneill 59 1.1 jmcneill static int 60 1.1 jmcneill au8522_reset(struct au8522 *au) 61 1.1 jmcneill { 62 1.1 jmcneill return au8522_write_1(au, 0xa4, 1 << 5); 63 1.1 jmcneill } 64 1.1 jmcneill 65 1.1 jmcneill static int 66 1.1 jmcneill au8522_read_1(struct au8522 *au, uint16_t reg, uint8_t *val) 67 1.1 jmcneill { 68 1.1 jmcneill uint8_t cmd[2]; 69 1.1 jmcneill int error; 70 1.1 jmcneill 71 1.1 jmcneill cmd[0] = (reg >> 8) | 0x40; 72 1.1 jmcneill cmd[1] = reg & 0xff; 73 1.1 jmcneill error = iic_exec(au->i2c, I2C_OP_WRITE, au->i2c_addr, 74 1.1 jmcneill cmd, sizeof(cmd), NULL, 0, 0); 75 1.1 jmcneill if (error) 76 1.1 jmcneill return error; 77 1.1 jmcneill return iic_exec(au->i2c, I2C_OP_READ, au->i2c_addr, 78 1.1 jmcneill NULL, 0, val, sizeof(*val), 0); 79 1.1 jmcneill } 80 1.1 jmcneill 81 1.1 jmcneill static int 82 1.1 jmcneill au8522_write_1(struct au8522 *au, uint16_t reg, uint8_t val) 83 1.1 jmcneill { 84 1.1 jmcneill uint8_t data[3]; 85 1.1 jmcneill 86 1.1 jmcneill data[0] = (reg >> 8) | 0x80; 87 1.1 jmcneill data[1] = reg & 0xff; 88 1.1 jmcneill data[2] = val; 89 1.1 jmcneill return iic_exec(au->i2c, I2C_OP_WRITE, au->i2c_addr, 90 1.1 jmcneill data, sizeof(data), NULL, 0, 0); 91 1.1 jmcneill } 92 1.1 jmcneill 93 1.1 jmcneill static int 94 1.1 jmcneill au8522_set_vinput(struct au8522 *au, au8522_vinput_t vi) 95 1.1 jmcneill { 96 1.1 jmcneill switch (vi) { 97 1.1 jmcneill case AU8522_VINPUT_CVBS: 98 1.1 jmcneill au8522_write_1(au, AU8522_REG_MODCLKCTL, AU8522_MODCLKCTL_CVBS); 99 1.1 jmcneill au8522_write_1(au, AU8522_REG_PGACTL, 0x00); 100 1.1 jmcneill au8522_write_1(au, AU8522_REG_CLAMPCTL, 0x0e); 101 1.1 jmcneill au8522_write_1(au, AU8522_REG_PGACTL, 0x10); 102 1.1 jmcneill au8522_write_1(au, AU8522_REG_INPUTCTL, 103 1.1 jmcneill AU8522_INPUTCTL_CVBS_CH1); 104 1.1 jmcneill 105 1.1 jmcneill au8522_set_common(au, vi); 106 1.1 jmcneill 107 1.1 jmcneill au8522_write_1(au, AU8522_REG_SYSMODCTL0, 108 1.1 jmcneill AU8522_SYSMODCTL0_CVBS); 109 1.1 jmcneill break; 110 1.1 jmcneill case AU8522_VINPUT_SVIDEO: 111 1.1 jmcneill au8522_write_1(au, AU8522_REG_MODCLKCTL, 112 1.1 jmcneill AU8522_MODCLKCTL_SVIDEO); 113 1.1 jmcneill au8522_write_1(au, AU8522_REG_INPUTCTL, 114 1.1 jmcneill AU8522_INPUTCTL_SVIDEO_CH13); 115 1.1 jmcneill au8522_write_1(au, AU8522_REG_CLAMPCTL, 0x00); 116 1.1 jmcneill 117 1.1 jmcneill au8522_set_common(au, vi); 118 1.1 jmcneill 119 1.1 jmcneill au8522_write_1(au, AU8522_REG_SYSMODCTL0, 120 1.1 jmcneill AU8522_SYSMODCTL0_CVBS); 121 1.1 jmcneill 122 1.1 jmcneill break; 123 1.1 jmcneill case AU8522_VINPUT_CVBS_TUNER: 124 1.1 jmcneill au8522_write_1(au, AU8522_REG_MODCLKCTL, AU8522_MODCLKCTL_CVBS); 125 1.1 jmcneill au8522_write_1(au, AU8522_REG_PGACTL, 0x00); 126 1.1 jmcneill au8522_write_1(au, AU8522_REG_CLAMPCTL, 0x0e); 127 1.1 jmcneill au8522_write_1(au, AU8522_REG_PGACTL, 0x10); 128 1.1 jmcneill au8522_write_1(au, AU8522_REG_INPUTCTL, 129 1.1 jmcneill AU8522_INPUTCTL_CVBS_CH4_SIF); 130 1.1 jmcneill 131 1.1 jmcneill au8522_set_common(au, vi); 132 1.1 jmcneill 133 1.1 jmcneill au8522_write_1(au, AU8522_REG_SYSMODCTL0, 134 1.1 jmcneill AU8522_SYSMODCTL0_CVBS); 135 1.1 jmcneill 136 1.1 jmcneill break; 137 1.1 jmcneill default: 138 1.1 jmcneill return EINVAL; 139 1.1 jmcneill } 140 1.1 jmcneill 141 1.1 jmcneill return 0; 142 1.1 jmcneill } 143 1.1 jmcneill 144 1.1 jmcneill static void 145 1.1 jmcneill au8522_set_common(struct au8522 *au, au8522_vinput_t vi) 146 1.1 jmcneill { 147 1.1 jmcneill au8522_write_1(au, AU8522_REG_INTMASK, 0x00); 148 1.1 jmcneill au8522_write_1(au, AU8522_REG_VIDEOMODE, vi == AU8522_VINPUT_SVIDEO ? 149 1.1 jmcneill AU8522_VIDEOMODE_SVIDEO : AU8522_VIDEOMODE_CVBS); 150 1.1 jmcneill au8522_write_1(au, AU8522_REG_TV_PGA, AU8522_TV_PGA_CVBS); 151 1.1 jmcneill } 152 1.1 jmcneill 153 1.1 jmcneill static int 154 1.1 jmcneill au8522_set_ainput(struct au8522 *au, au8522_ainput_t ai) 155 1.1 jmcneill { 156 1.1 jmcneill /* mute during mode change */ 157 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL_L, 0x00); 158 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL_R, 0x00); 159 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL, 0x00); 160 1.1 jmcneill 161 1.1 jmcneill switch (ai) { 162 1.1 jmcneill case AU8522_AINPUT_SIF: 163 1.1 jmcneill au8522_write_1(au, AU8522_REG_SYSMODCTL0, 164 1.1 jmcneill AU8522_SYSMODCTL0_CVBS); 165 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_MODE, 0x82); 166 1.1 jmcneill au8522_write_1(au, AU8522_REG_SYSMODCTL1, 167 1.1 jmcneill AU8522_SYSMODCTL1_I2S); 168 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_FREQ, 0x03); 169 1.1 jmcneill au8522_write_1(au, AU8522_REG_I2S_CTL2, 0xc2); 170 1.1 jmcneill /* unmute */ 171 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL_L, 0x7f); 172 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL_R, 0x7f); 173 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL, 0xff); 174 1.1 jmcneill break; 175 1.1 jmcneill case AU8522_AINPUT_NONE: 176 1.1 jmcneill au8522_write_1(au, AU8522_REG_USBEN, 0x00); 177 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL_L, 0x7f); 178 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL_R, 0x7f); 179 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_MODE, 0x40); 180 1.1 jmcneill au8522_write_1(au, AU8522_REG_SYSMODCTL1, 181 1.1 jmcneill AU8522_SYSMODCTL1_SVIDEO); 182 1.1 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_FREQ, 0x03); 183 1.1 jmcneill au8522_write_1(au, AU8522_REG_I2S_CTL2, 0x02); 184 1.1 jmcneill au8522_write_1(au, AU8522_REG_SYSMODCTL0, 185 1.1 jmcneill AU8522_SYSMODCTL0_CVBS); 186 1.1 jmcneill break; 187 1.1 jmcneill default: 188 1.1 jmcneill return EINVAL; 189 1.1 jmcneill } 190 1.1 jmcneill return 0; 191 1.1 jmcneill } 192 1.1 jmcneill 193 1.4 jmcneill static int 194 1.4 jmcneill au8522_set_if(struct au8522 *au) 195 1.4 jmcneill { 196 1.4 jmcneill uint8_t ifinit[3]; 197 1.4 jmcneill unsigned int n; 198 1.4 jmcneill 199 1.4 jmcneill switch (au->if_freq) { 200 1.4 jmcneill case 6000000: /* 6MHz */ 201 1.4 jmcneill ifinit[0] = 0xfb; 202 1.4 jmcneill ifinit[1] = 0x8e; 203 1.4 jmcneill ifinit[2] = 0x39; 204 1.4 jmcneill break; 205 1.4 jmcneill default: 206 1.4 jmcneill aprint_error_dev(au->parent, "au8522: unsupported if freq %dHz\n", au->if_freq); 207 1.4 jmcneill return EINVAL; 208 1.4 jmcneill } 209 1.4 jmcneill 210 1.4 jmcneill for (n = 0; n < __arraycount(ifinit); n++) 211 1.4 jmcneill au8522_write_1(au, 0x80b5 + n, ifinit[n]); 212 1.4 jmcneill 213 1.4 jmcneill return 0; 214 1.4 jmcneill } 215 1.4 jmcneill 216 1.1 jmcneill struct au8522 * 217 1.4 jmcneill au8522_open(device_t parent, i2c_tag_t i2c, i2c_addr_t addr, unsigned int if_freq) 218 1.1 jmcneill { 219 1.1 jmcneill struct au8522 *au; 220 1.1 jmcneill 221 1.1 jmcneill au = kmem_alloc(sizeof(*au), KM_SLEEP); 222 1.1 jmcneill au->parent = parent; 223 1.1 jmcneill au->i2c = i2c; 224 1.1 jmcneill au->i2c_addr = addr; 225 1.4 jmcneill au->current_modulation = -1; 226 1.4 jmcneill au->if_freq = if_freq; 227 1.1 jmcneill 228 1.1 jmcneill if (au8522_reset(au)) 229 1.1 jmcneill goto failed; 230 1.1 jmcneill if (au8522_write_1(au, AU8522_REG_TUNERCTL, AU8522_TUNERCTL_EN)) 231 1.1 jmcneill goto failed; 232 1.1 jmcneill 233 1.1 jmcneill return au; 234 1.1 jmcneill 235 1.1 jmcneill failed: 236 1.1 jmcneill kmem_free(au, sizeof(*au)); 237 1.1 jmcneill return NULL; 238 1.1 jmcneill } 239 1.1 jmcneill 240 1.1 jmcneill void 241 1.1 jmcneill au8522_close(struct au8522 *au) 242 1.1 jmcneill { 243 1.1 jmcneill kmem_free(au, sizeof(*au)); 244 1.1 jmcneill } 245 1.1 jmcneill 246 1.1 jmcneill void 247 1.1 jmcneill au8522_enable(struct au8522 *au, bool enable) 248 1.1 jmcneill { 249 1.1 jmcneill if (enable) { 250 1.1 jmcneill au8522_write_1(au, AU8522_REG_SYSMODCTL0, 251 1.1 jmcneill AU8522_SYSMODCTL0_RESET); 252 1.1 jmcneill delay(1000); 253 1.1 jmcneill au8522_write_1(au, AU8522_REG_SYSMODCTL0, 254 1.1 jmcneill AU8522_SYSMODCTL0_CVBS); 255 1.1 jmcneill } else { 256 1.1 jmcneill au8522_write_1(au, AU8522_REG_SYSMODCTL0, 257 1.1 jmcneill AU8522_SYSMODCTL0_DISABLE); 258 1.1 jmcneill } 259 1.1 jmcneill } 260 1.1 jmcneill 261 1.1 jmcneill void 262 1.1 jmcneill au8522_set_input(struct au8522 *au, au8522_vinput_t vi, au8522_ainput_t ai) 263 1.1 jmcneill { 264 1.1 jmcneill au8522_reset(au); 265 1.1 jmcneill 266 1.1 jmcneill if (vi != AU8522_VINPUT_UNCONF) 267 1.1 jmcneill au8522_set_vinput(au, vi); 268 1.1 jmcneill if (ai != AU8522_AINPUT_UNCONF) 269 1.1 jmcneill au8522_set_ainput(au, ai); 270 1.1 jmcneill } 271 1.1 jmcneill 272 1.1 jmcneill int 273 1.1 jmcneill au8522_get_signal(struct au8522 *au) 274 1.1 jmcneill { 275 1.1 jmcneill uint8_t status; 276 1.1 jmcneill 277 1.1 jmcneill if (au8522_read_1(au, AU8522_REG_STATUS, &status)) 278 1.1 jmcneill return 0; 279 1.1 jmcneill 280 1.1 jmcneill #ifdef AU8522_DEBUG 281 1.1 jmcneill printf("au8522: status=0x%02x\n", status); 282 1.1 jmcneill #endif 283 1.1 jmcneill return (status & AU8522_STATUS_LOCK) == AU8522_STATUS_LOCK ? 1 : 0; 284 1.1 jmcneill } 285 1.1 jmcneill 286 1.3 jmcneill void 287 1.3 jmcneill au8522_set_audio(struct au8522 *au, bool onoff) 288 1.3 jmcneill { 289 1.3 jmcneill if (onoff) { 290 1.3 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL_L, 0x7f); 291 1.3 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL_R, 0x7f); 292 1.3 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL, 0xff); 293 1.3 jmcneill } else { 294 1.3 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL_L, 0x00); 295 1.3 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL_R, 0x00); 296 1.3 jmcneill au8522_write_1(au, AU8522_REG_AUDIO_VOL, 0x00); 297 1.3 jmcneill } 298 1.3 jmcneill } 299 1.3 jmcneill 300 1.4 jmcneill int 301 1.4 jmcneill au8522_set_modulation(struct au8522 *au, fe_modulation_t modulation) 302 1.4 jmcneill { 303 1.4 jmcneill const struct au8522_modulation_table *modtab = NULL; 304 1.4 jmcneill size_t modtablen; 305 1.4 jmcneill unsigned int n; 306 1.4 jmcneill 307 1.4 jmcneill switch (modulation) { 308 1.4 jmcneill case VSB_8: 309 1.4 jmcneill modtab = au8522_modulation_8vsb; 310 1.4 jmcneill modtablen = __arraycount(au8522_modulation_8vsb); 311 1.4 jmcneill break; 312 1.4 jmcneill case QAM_64: 313 1.4 jmcneill modtab = au8522_modulation_qam64; 314 1.4 jmcneill modtablen = __arraycount(au8522_modulation_qam64); 315 1.4 jmcneill break; 316 1.4 jmcneill case QAM_256: 317 1.4 jmcneill modtab = au8522_modulation_qam256; 318 1.4 jmcneill modtablen = __arraycount(au8522_modulation_qam256); 319 1.4 jmcneill break; 320 1.4 jmcneill default: 321 1.4 jmcneill return EINVAL; 322 1.4 jmcneill } 323 1.4 jmcneill 324 1.4 jmcneill for (n = 0; n < modtablen; n++) 325 1.4 jmcneill au8522_write_1(au, modtab[n].reg, modtab[n].val); 326 1.4 jmcneill 327 1.4 jmcneill au8522_set_if(au); 328 1.4 jmcneill 329 1.4 jmcneill au->current_modulation = modulation; 330 1.4 jmcneill 331 1.4 jmcneill return 0; 332 1.4 jmcneill } 333 1.4 jmcneill 334 1.4 jmcneill void 335 1.4 jmcneill au8522_set_gate(struct au8522 *au, bool onoff) 336 1.4 jmcneill { 337 1.4 jmcneill au8522_write_1(au, AU8522_REG_TUNERCTL, onoff ? AU8522_TUNERCTL_EN : 0); 338 1.4 jmcneill } 339 1.4 jmcneill 340 1.4 jmcneill fe_status_t 341 1.4 jmcneill au8522_get_dtv_status(struct au8522 *au) 342 1.4 jmcneill { 343 1.4 jmcneill fe_status_t status = 0; 344 1.4 jmcneill uint8_t val; 345 1.4 jmcneill 346 1.4 jmcneill switch (au->current_modulation) { 347 1.4 jmcneill case VSB_8: 348 1.4 jmcneill if (au8522_read_1(au, 0x4088, &val)) 349 1.4 jmcneill return 0; 350 1.4 jmcneill if ((val & 0x03) == 0x03) { 351 1.4 jmcneill status |= FE_HAS_SIGNAL; 352 1.4 jmcneill status |= FE_HAS_CARRIER; 353 1.4 jmcneill status |= FE_HAS_VITERBI; 354 1.4 jmcneill } 355 1.4 jmcneill break; 356 1.4 jmcneill case QAM_64: 357 1.4 jmcneill case QAM_256: 358 1.4 jmcneill if (au8522_read_1(au, 0x4541, &val)) 359 1.4 jmcneill return 0; 360 1.4 jmcneill if (val & 0x80) { 361 1.4 jmcneill status |= FE_HAS_VITERBI; 362 1.4 jmcneill } 363 1.4 jmcneill if (val & 0x20) { 364 1.4 jmcneill status |= FE_HAS_SIGNAL; 365 1.4 jmcneill status |= FE_HAS_CARRIER; 366 1.4 jmcneill } 367 1.4 jmcneill break; 368 1.4 jmcneill default: 369 1.4 jmcneill break; 370 1.4 jmcneill } 371 1.4 jmcneill 372 1.4 jmcneill if (status & FE_HAS_VITERBI) { 373 1.4 jmcneill status |= FE_HAS_SYNC; 374 1.4 jmcneill status |= FE_HAS_LOCK; 375 1.4 jmcneill } 376 1.4 jmcneill 377 1.4 jmcneill return status; 378 1.4 jmcneill } 379 1.4 jmcneill 380 1.5 jmcneill uint16_t 381 1.5 jmcneill au8522_get_snr(struct au8522 *au) 382 1.5 jmcneill { 383 1.5 jmcneill const struct au8522_snr_table *snrtab = NULL; 384 1.5 jmcneill uint16_t snrreg; 385 1.5 jmcneill uint8_t val; 386 1.5 jmcneill size_t snrtablen; 387 1.5 jmcneill unsigned int n; 388 1.5 jmcneill 389 1.5 jmcneill switch (au->current_modulation) { 390 1.5 jmcneill case VSB_8: 391 1.5 jmcneill snrtab = au8522_snr_8vsb; 392 1.5 jmcneill snrtablen = __arraycount(au8522_snr_8vsb); 393 1.5 jmcneill snrreg = AU8522_REG_SNR_VSB; 394 1.5 jmcneill break; 395 1.5 jmcneill case QAM_64: 396 1.5 jmcneill snrtab = au8522_snr_qam64; 397 1.5 jmcneill snrtablen = __arraycount(au8522_snr_qam64); 398 1.5 jmcneill snrreg = AU8522_REG_SNR_QAM; 399 1.5 jmcneill break; 400 1.5 jmcneill case QAM_256: 401 1.5 jmcneill snrtab = au8522_snr_qam256; 402 1.5 jmcneill snrtablen = __arraycount(au8522_snr_qam256); 403 1.5 jmcneill snrreg = AU8522_REG_SNR_QAM; 404 1.5 jmcneill break; 405 1.5 jmcneill default: 406 1.5 jmcneill return 0; 407 1.5 jmcneill } 408 1.5 jmcneill 409 1.5 jmcneill if (au8522_read_1(au, snrreg, &val)) 410 1.5 jmcneill return 0; 411 1.5 jmcneill 412 1.5 jmcneill for (n = 0; n < snrtablen; n++) { 413 1.5 jmcneill if (val < snrtab[n].val) 414 1.5 jmcneill return snrtab[n].snr; 415 1.5 jmcneill } 416 1.5 jmcneill 417 1.5 jmcneill return 0; 418 1.5 jmcneill } 419 1.5 jmcneill 420 1.7 jmcneill MODULE(MODULE_CLASS_DRIVER, au8522, "i2cexec"); 421 1.1 jmcneill 422 1.1 jmcneill static int 423 1.1 jmcneill au8522_modcmd(modcmd_t cmd, void *opaque) 424 1.1 jmcneill { 425 1.1 jmcneill switch (cmd) { 426 1.1 jmcneill case MODULE_CMD_INIT: 427 1.1 jmcneill return 0; 428 1.1 jmcneill case MODULE_CMD_FINI: 429 1.1 jmcneill return 0; 430 1.1 jmcneill default: 431 1.1 jmcneill return ENOTTY; 432 1.1 jmcneill } 433 1.1 jmcneill } 434