1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // aw87390.c -- AW87390 ALSA SoC Audio driver 4 // 5 // Copyright (c) 2023 awinic Technology CO., LTD 6 // 7 // Author: Weidong Wang <wangweidong.a@awinic.com> 8 // 9 10 #include <linux/cleanup.h> 11 #include <linux/i2c.h> 12 #include <linux/firmware.h> 13 #include <linux/regmap.h> 14 #include <sound/soc.h> 15 #include "aw87390.h" 16 #include "aw88395/aw88395_data_type.h" 17 #include "aw88395/aw88395_device.h" 18 19 static const struct regmap_config aw87390_remap_config = { 20 .val_bits = 8, 21 .reg_bits = 8, 22 .max_register = AW87390_REG_MAX, 23 .reg_format_endian = REGMAP_ENDIAN_LITTLE, 24 .val_format_endian = REGMAP_ENDIAN_BIG, 25 }; 26 27 static int aw87390_dev_reg_update(struct aw_device *aw_dev, 28 unsigned char *data, unsigned int len) 29 { 30 int i, ret; 31 32 if (!data) { 33 dev_err(aw_dev->dev, "data is NULL\n"); 34 return -EINVAL; 35 } 36 37 for (i = 0; i < len-1; i += 2) { 38 if (data[i] == AW87390_DELAY_REG_ADDR) { 39 usleep_range(data[i + 1] * AW87390_REG_DELAY_TIME, 40 data[i + 1] * AW87390_REG_DELAY_TIME + 10); 41 continue; 42 } 43 ret = regmap_write(aw_dev->regmap, data[i], data[i + 1]); 44 if (ret) 45 return ret; 46 } 47 48 return 0; 49 } 50 51 static int aw87390_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name) 52 { 53 struct aw_prof_info *prof_info = &aw_dev->prof_info; 54 struct aw_prof_desc *prof_desc; 55 56 if ((index >= aw_dev->prof_info.count) || (index < 0)) { 57 dev_err(aw_dev->dev, "index[%d] overflow count[%d]\n", 58 index, aw_dev->prof_info.count); 59 return -EINVAL; 60 } 61 62 prof_desc = &aw_dev->prof_info.prof_desc[index]; 63 64 *prof_name = prof_info->prof_name_list[prof_desc->id]; 65 66 return 0; 67 } 68 69 static int aw87390_dev_get_prof_data(struct aw_device *aw_dev, int index, 70 struct aw_prof_desc **prof_desc) 71 { 72 if ((index >= aw_dev->prof_info.count) || (index < 0)) { 73 dev_err(aw_dev->dev, "%s: index[%d] overflow count[%d]\n", 74 __func__, index, aw_dev->prof_info.count); 75 return -EINVAL; 76 } 77 78 *prof_desc = &aw_dev->prof_info.prof_desc[index]; 79 80 return 0; 81 } 82 83 static int aw87390_dev_fw_update(struct aw_device *aw_dev) 84 { 85 struct aw_prof_desc *prof_index_desc; 86 struct aw_sec_data_desc *sec_desc; 87 char *prof_name; 88 int ret; 89 90 ret = aw87390_dev_get_prof_name(aw_dev, aw_dev->prof_index, &prof_name); 91 if (ret) { 92 dev_err(aw_dev->dev, "get prof name failed\n"); 93 return -EINVAL; 94 } 95 96 dev_dbg(aw_dev->dev, "start update %s", prof_name); 97 98 ret = aw87390_dev_get_prof_data(aw_dev, aw_dev->prof_index, &prof_index_desc); 99 if (ret) { 100 dev_err(aw_dev->dev, "aw87390_dev_get_prof_data failed\n"); 101 return ret; 102 } 103 104 /* update reg */ 105 sec_desc = prof_index_desc->sec_desc; 106 ret = aw87390_dev_reg_update(aw_dev, sec_desc[AW88395_DATA_TYPE_REG].data, 107 sec_desc[AW88395_DATA_TYPE_REG].len); 108 if (ret) { 109 dev_err(aw_dev->dev, "update reg failed\n"); 110 return ret; 111 } 112 113 aw_dev->prof_cur = aw_dev->prof_index; 114 115 return 0; 116 } 117 118 static int aw87390_power_off(struct aw_device *aw_dev) 119 { 120 int ret; 121 122 if (aw_dev->status == AW87390_DEV_PW_OFF) { 123 dev_dbg(aw_dev->dev, "already power off\n"); 124 return 0; 125 } 126 127 ret = regmap_write(aw_dev->regmap, AW87390_SYSCTRL_REG, AW87390_POWER_DOWN_VALUE); 128 if (ret) 129 return ret; 130 aw_dev->status = AW87390_DEV_PW_OFF; 131 132 return 0; 133 } 134 135 static int aw87390_power_on(struct aw_device *aw_dev) 136 { 137 int ret; 138 139 if (aw_dev->status == AW87390_DEV_PW_ON) { 140 dev_dbg(aw_dev->dev, "already power on\n"); 141 return 0; 142 } 143 144 if (!aw_dev->fw_status) { 145 dev_err(aw_dev->dev, "fw not load\n"); 146 return -EINVAL; 147 } 148 149 ret = regmap_write(aw_dev->regmap, AW87390_SYSCTRL_REG, AW87390_POWER_DOWN_VALUE); 150 if (ret) 151 return ret; 152 153 ret = aw87390_dev_fw_update(aw_dev); 154 if (ret) { 155 dev_err(aw_dev->dev, "%s load profile failed\n", __func__); 156 return ret; 157 } 158 aw_dev->status = AW87390_DEV_PW_ON; 159 160 return 0; 161 } 162 163 static int aw87390_dev_set_profile_index(struct aw_device *aw_dev, int index) 164 { 165 if ((index >= aw_dev->prof_info.count) || (index < 0)) 166 return -EINVAL; 167 168 if (aw_dev->prof_index == index) 169 return -EPERM; 170 171 aw_dev->prof_index = index; 172 173 return 0; 174 } 175 176 static int aw87390_profile_info(struct snd_kcontrol *kcontrol, 177 struct snd_ctl_elem_info *uinfo) 178 { 179 struct snd_soc_component *codec = snd_kcontrol_chip(kcontrol); 180 struct aw87390 *aw87390 = snd_soc_component_get_drvdata(codec); 181 char *prof_name; 182 int count, ret; 183 184 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 185 uinfo->count = 1; 186 187 count = aw87390->aw_pa->prof_info.count; 188 if (count <= 0) { 189 uinfo->value.enumerated.items = 0; 190 return 0; 191 } 192 193 uinfo->value.enumerated.items = count; 194 195 if (uinfo->value.enumerated.item >= count) 196 uinfo->value.enumerated.item = count - 1; 197 198 count = uinfo->value.enumerated.item; 199 200 ret = aw87390_dev_get_prof_name(aw87390->aw_pa, count, &prof_name); 201 if (ret) { 202 strscpy(uinfo->value.enumerated.name, "null"); 203 return 0; 204 } 205 206 strscpy(uinfo->value.enumerated.name, prof_name); 207 208 return 0; 209 } 210 211 static int aw87390_profile_get(struct snd_kcontrol *kcontrol, 212 struct snd_ctl_elem_value *ucontrol) 213 { 214 struct snd_soc_component *codec = snd_kcontrol_chip(kcontrol); 215 struct aw87390 *aw87390 = snd_soc_component_get_drvdata(codec); 216 217 ucontrol->value.integer.value[0] = aw87390->aw_pa->prof_index; 218 219 return 0; 220 } 221 222 static int aw87390_profile_set(struct snd_kcontrol *kcontrol, 223 struct snd_ctl_elem_value *ucontrol) 224 { 225 struct snd_soc_component *codec = snd_kcontrol_chip(kcontrol); 226 struct aw87390 *aw87390 = snd_soc_component_get_drvdata(codec); 227 int ret; 228 229 guard(mutex)(&aw87390->lock); 230 ret = aw87390_dev_set_profile_index(aw87390->aw_pa, ucontrol->value.integer.value[0]); 231 if (ret) { 232 dev_dbg(codec->dev, "profile index does not change\n"); 233 return 0; 234 } 235 236 if (aw87390->aw_pa->status == AW87390_DEV_PW_ON) { 237 aw87390_power_off(aw87390->aw_pa); 238 aw87390_power_on(aw87390->aw_pa); 239 } 240 241 return 1; 242 } 243 244 static const struct snd_kcontrol_new aw87390_controls[] = { 245 AW87390_PROFILE_EXT("AW87390 Profile Set", aw87390_profile_info, 246 aw87390_profile_get, aw87390_profile_set), 247 }; 248 249 static int aw87390_request_firmware_file(struct aw87390 *aw87390) 250 { 251 const struct firmware *cont __free(firmware) = NULL; 252 int ret; 253 254 aw87390->aw_pa->fw_status = AW87390_DEV_FW_FAILED; 255 256 ret = request_firmware(&cont, AW87390_ACF_FILE, aw87390->aw_pa->dev); 257 if (ret) 258 return dev_err_probe(aw87390->aw_pa->dev, ret, 259 "load [%s] failed!\n", AW87390_ACF_FILE); 260 261 dev_dbg(aw87390->aw_pa->dev, "loaded %s - size: %zu\n", 262 AW87390_ACF_FILE, cont ? cont->size : 0); 263 264 aw87390->aw_cfg = devm_kzalloc(aw87390->aw_pa->dev, 265 struct_size(aw87390->aw_cfg, data, cont->size), GFP_KERNEL); 266 if (!aw87390->aw_cfg) 267 return -ENOMEM; 268 269 aw87390->aw_cfg->len = cont->size; 270 memcpy(aw87390->aw_cfg->data, cont->data, cont->size); 271 272 ret = aw88395_dev_load_acf_check(aw87390->aw_pa, aw87390->aw_cfg); 273 if (ret) { 274 dev_err(aw87390->aw_pa->dev, "load [%s] failed!\n", AW87390_ACF_FILE); 275 return ret; 276 } 277 278 guard(mutex)(&aw87390->lock); 279 280 ret = aw88395_dev_cfg_load(aw87390->aw_pa, aw87390->aw_cfg); 281 if (ret) 282 dev_err(aw87390->aw_pa->dev, "aw_dev acf parse failed\n"); 283 284 return ret; 285 } 286 287 static int aw87390_drv_event(struct snd_soc_dapm_widget *w, 288 struct snd_kcontrol *kcontrol, int event) 289 { 290 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 291 struct aw87390 *aw87390 = snd_soc_component_get_drvdata(component); 292 struct aw_device *aw_dev = aw87390->aw_pa; 293 int ret; 294 295 switch (event) { 296 case SND_SOC_DAPM_PRE_PMU: 297 ret = aw87390_power_on(aw_dev); 298 break; 299 case SND_SOC_DAPM_POST_PMD: 300 ret = aw87390_power_off(aw_dev); 301 break; 302 default: 303 dev_err(aw_dev->dev, "%s: invalid event %d\n", __func__, event); 304 ret = -EINVAL; 305 } 306 307 return ret; 308 } 309 310 static int aw87391_rgds_drv_event(struct snd_soc_dapm_widget *w, 311 struct snd_kcontrol *kcontrol, int event) 312 { 313 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 314 struct aw87390 *aw87390 = snd_soc_component_get_drvdata(component); 315 struct aw_device *aw_dev = aw87390->aw_pa; 316 317 switch (event) { 318 case SND_SOC_DAPM_PRE_PMU: 319 if (!IS_ERR(aw87390->vdd_reg)) { 320 if (regulator_enable(aw87390->vdd_reg)) 321 dev_warn(aw_dev->dev, "Failed to enable vdd\n"); 322 } 323 break; 324 case SND_SOC_DAPM_POST_PMU: 325 regmap_write(aw_dev->regmap, AW87391_SYSCTRL_REG, 326 AW87391_REG_VER_SEL_LOW | AW87391_REG_EN_ADAP | 327 AW87391_REG_EN_2X | AW87391_EN_SPK | 328 AW87391_EN_PA | AW87391_REG_EN_CP | 329 AW87391_EN_SW); 330 break; 331 case SND_SOC_DAPM_PRE_PMD: 332 regmap_write(aw_dev->regmap, AW87390_SYSCTRL_REG, 333 AW87390_POWER_DOWN_VALUE); 334 break; 335 case SND_SOC_DAPM_POST_PMD: 336 if (!IS_ERR(aw87390->vdd_reg)) { 337 if (regulator_disable(aw87390->vdd_reg)) 338 dev_warn(aw_dev->dev, "Failed to disable vdd\n"); 339 } 340 break; 341 default: 342 dev_err(aw_dev->dev, "%s: invalid event %d\n", __func__, event); 343 return -EINVAL; 344 } 345 346 return 0; 347 } 348 349 static const struct snd_soc_dapm_widget aw87390_dapm_widgets[] = { 350 SND_SOC_DAPM_INPUT("IN"), 351 SND_SOC_DAPM_PGA_E("SPK PA", SND_SOC_NOPM, 0, 0, NULL, 0, aw87390_drv_event, 352 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 353 SND_SOC_DAPM_OUTPUT("OUT"), 354 }; 355 356 static const struct snd_soc_dapm_widget aw87391_rgds_dapm_widgets[] = { 357 SND_SOC_DAPM_INPUT("IN"), 358 SND_SOC_DAPM_PGA_E("SPK PA", SND_SOC_NOPM, 0, 0, NULL, 0, aw87391_rgds_drv_event, 359 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 360 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 361 SND_SOC_DAPM_OUTPUT("OUT"), 362 }; 363 364 static const struct snd_soc_dapm_route aw87390_dapm_routes[] = { 365 { "SPK PA", NULL, "IN" }, 366 { "OUT", NULL, "SPK PA" }, 367 }; 368 369 static int aw87390_codec_probe(struct snd_soc_component *component) 370 { 371 struct aw87390 *aw87390 = snd_soc_component_get_drvdata(component); 372 int ret; 373 374 ret = aw87390_request_firmware_file(aw87390); 375 if (ret) 376 return dev_err_probe(aw87390->aw_pa->dev, ret, 377 "aw87390_request_firmware_file failed\n"); 378 379 return 0; 380 } 381 382 /* 383 * Firmware typically is used to load the sequence of init commands, 384 * however for the Anbernic RG-DS we don't have a firmware file just 385 * a list of registers and values. Most of these values are undocumented 386 * in the AW87391 datasheet. 387 */ 388 static void aw87391_rgds_codec_init(struct aw87390 *aw87390) 389 { 390 struct aw_device *aw_dev = aw87390->aw_pa; 391 392 /* Undocumented command per datasheet. */ 393 regmap_write(aw_dev->regmap, 0x64, 0x3a); 394 395 /* Bits 7:4 are undocumented but provided by manufacturer. */ 396 regmap_write(aw_dev->regmap, AW87391_CP_REG, 397 (5 << 4) | AW87391_REG_CP_OVP_8_50V); 398 399 regmap_write(aw_dev->regmap, AW87391_AGCPO_REG, 400 AW87391_AK1_S_016 | AW87391_AGC2PO_MW(500)); 401 402 regmap_write(aw_dev->regmap, AW87391_AGC2PA_REG, 403 AW87391_RK_S_20_48 | AW87391_AK2_S_41 | AW87391_AK2F_S_41); 404 405 /* Undocumented commands per datasheet. */ 406 regmap_write(aw_dev->regmap, 0x5d, 0x00); 407 regmap_write(aw_dev->regmap, 0x5e, 0xb4); 408 regmap_write(aw_dev->regmap, 0x5f, 0x30); 409 regmap_write(aw_dev->regmap, 0x60, 0x39); 410 regmap_write(aw_dev->regmap, 0x61, 0x10); 411 regmap_write(aw_dev->regmap, 0x62, 0x03); 412 regmap_write(aw_dev->regmap, 0x63, 0x7d); 413 regmap_write(aw_dev->regmap, 0x65, 0xa0); 414 regmap_write(aw_dev->regmap, 0x66, 0x21); 415 regmap_write(aw_dev->regmap, 0x67, 0x41); 416 regmap_write(aw_dev->regmap, 0x68, 0x3b); 417 regmap_write(aw_dev->regmap, 0x6e, 0x00); 418 regmap_write(aw_dev->regmap, 0x6f, 0x00); 419 regmap_write(aw_dev->regmap, 0x70, 0x00); 420 regmap_write(aw_dev->regmap, 0x71, 0x00); 421 regmap_write(aw_dev->regmap, 0x72, 0x34); 422 regmap_write(aw_dev->regmap, 0x73, 0x06); 423 regmap_write(aw_dev->regmap, 0x74, 0x10); 424 regmap_write(aw_dev->regmap, 0x75, 0x00); 425 regmap_write(aw_dev->regmap, 0x7a, 0x00); 426 regmap_write(aw_dev->regmap, 0x7b, 0x00); 427 regmap_write(aw_dev->regmap, 0x7c, 0x00); 428 regmap_write(aw_dev->regmap, 0x7d, 0x00); 429 430 regmap_write(aw_dev->regmap, AW87391_PAG_REG, AW87391_GAIN_12DB); 431 regmap_write(aw_dev->regmap, AW87391_SYSCTRL_REG, 432 AW87391_EN_PA | AW87391_REG_EN_CP | AW87391_EN_SW); 433 regmap_write(aw_dev->regmap, AW87391_SYSCTRL_REG, 434 AW87391_REG_VER_SEL_LOW | AW87391_REG_EN_ADAP | 435 AW87391_REG_EN_2X | AW87391_EN_SPK | AW87391_EN_PA | 436 AW87391_REG_EN_CP | AW87391_EN_SW); 437 regmap_write(aw_dev->regmap, AW87391_PAG_REG, AW87391_GAIN_15DB); 438 } 439 440 static int aw87391_rgds_codec_probe(struct snd_soc_component *component) 441 { 442 struct aw87390 *aw87390 = snd_soc_component_get_drvdata(component); 443 444 aw87390->vdd_reg = devm_regulator_get_optional(aw87390->aw_pa->dev, 445 "vdd"); 446 if (IS_ERR(aw87390->vdd_reg) && PTR_ERR(aw87390->vdd_reg) != -ENODEV) 447 return dev_err_probe(aw87390->aw_pa->dev, 448 PTR_ERR(aw87390->vdd_reg), 449 "Could not get vdd regulator\n"); 450 451 aw87391_rgds_codec_init(aw87390); 452 453 return 0; 454 } 455 456 static const struct snd_soc_component_driver soc_codec_dev_aw87390 = { 457 .probe = aw87390_codec_probe, 458 .dapm_widgets = aw87390_dapm_widgets, 459 .num_dapm_widgets = ARRAY_SIZE(aw87390_dapm_widgets), 460 .dapm_routes = aw87390_dapm_routes, 461 .num_dapm_routes = ARRAY_SIZE(aw87390_dapm_routes), 462 .controls = aw87390_controls, 463 .num_controls = ARRAY_SIZE(aw87390_controls), 464 }; 465 466 static const struct snd_soc_component_driver soc_codec_dev_anbernic_rgds = { 467 .probe = aw87391_rgds_codec_probe, 468 .dapm_widgets = aw87391_rgds_dapm_widgets, 469 .num_dapm_widgets = ARRAY_SIZE(aw87391_rgds_dapm_widgets), 470 .dapm_routes = aw87390_dapm_routes, 471 .num_dapm_routes = ARRAY_SIZE(aw87390_dapm_routes), 472 }; 473 474 static void aw87390_parse_channel_dt(struct aw87390 *aw87390) 475 { 476 struct aw_device *aw_dev = aw87390->aw_pa; 477 struct device_node *np = aw_dev->dev->of_node; 478 u32 channel_value = AW87390_DEV_DEFAULT_CH; 479 480 of_property_read_u32(np, "awinic,audio-channel", &channel_value); 481 482 aw_dev->channel = channel_value; 483 } 484 485 static int aw87390_init(struct aw87390 *aw87390, struct i2c_client *i2c, struct regmap *regmap) 486 { 487 struct aw_device *aw_dev; 488 unsigned int chip_id; 489 int ret; 490 491 aw_dev = devm_kzalloc(&i2c->dev, sizeof(*aw_dev), GFP_KERNEL); 492 if (!aw_dev) 493 return -ENOMEM; 494 495 /* read chip id */ 496 ret = regmap_read(regmap, AW87390_ID_REG, &chip_id); 497 if (ret) { 498 dev_err(&i2c->dev, "%s read chipid error. ret = %d\n", __func__, ret); 499 return ret; 500 } 501 502 switch (chip_id) { 503 case AW87390_CHIP_ID: 504 aw_dev->chip_id = AW87390_CHIP_ID; 505 break; 506 case AW87391_CHIP_ID: 507 aw_dev->chip_id = AW87391_CHIP_ID; 508 break; 509 default: 510 dev_err(&i2c->dev, "unsupported device\n"); 511 return -ENXIO; 512 } 513 514 dev_dbg(&i2c->dev, "chip id = 0x%x\n", chip_id); 515 516 aw87390->aw_pa = aw_dev; 517 aw_dev->i2c = i2c; 518 aw_dev->regmap = regmap; 519 aw_dev->dev = &i2c->dev; 520 aw_dev->acf = NULL; 521 aw_dev->prof_info.prof_desc = NULL; 522 aw_dev->prof_info.count = 0; 523 aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID; 524 aw_dev->channel = AW87390_DEV_DEFAULT_CH; 525 aw_dev->fw_status = AW87390_DEV_FW_FAILED; 526 aw_dev->prof_index = AW87390_INIT_PROFILE; 527 aw_dev->status = AW87390_DEV_PW_OFF; 528 529 aw87390_parse_channel_dt(aw87390); 530 531 return 0; 532 } 533 534 static int aw87390_i2c_probe(struct i2c_client *i2c) 535 { 536 struct aw87390 *aw87390; 537 const struct snd_soc_component_driver *priv; 538 int ret; 539 540 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) 541 return dev_err_probe(&i2c->dev, -ENXIO, "check_functionality failed\n"); 542 543 aw87390 = devm_kzalloc(&i2c->dev, sizeof(*aw87390), GFP_KERNEL); 544 if (!aw87390) 545 return -ENOMEM; 546 547 mutex_init(&aw87390->lock); 548 549 i2c_set_clientdata(i2c, aw87390); 550 551 aw87390->regmap = devm_regmap_init_i2c(i2c, &aw87390_remap_config); 552 if (IS_ERR(aw87390->regmap)) 553 return dev_err_probe(&i2c->dev, PTR_ERR(aw87390->regmap), 554 "failed to init regmap\n"); 555 556 /* aw pa init */ 557 ret = aw87390_init(aw87390, i2c, aw87390->regmap); 558 if (ret) 559 return ret; 560 561 ret = regmap_write(aw87390->regmap, AW87390_ID_REG, AW87390_SOFT_RESET_VALUE); 562 if (ret) 563 return ret; 564 565 switch (aw87390->aw_pa->chip_id) { 566 case AW87390_CHIP_ID: 567 ret = devm_snd_soc_register_component(&i2c->dev, 568 &soc_codec_dev_aw87390, NULL, 0); 569 break; 570 case AW87391_CHIP_ID: 571 priv = of_device_get_match_data(&i2c->dev); 572 if (!priv) 573 return dev_err_probe(&i2c->dev, -EINVAL, 574 "aw87391 not currently supported\n"); 575 ret = devm_snd_soc_register_component(&i2c->dev, priv, NULL, 0); 576 break; 577 default: 578 return -ENXIO; 579 } 580 581 if (ret) 582 dev_err(&i2c->dev, "failed to register aw87390: %d\n", ret); 583 584 return ret; 585 } 586 587 static const struct of_device_id aw87390_of_match[] = { 588 { .compatible = "awinic,aw87390" }, 589 { .compatible = "anbernic,rgds-amp", .data = &soc_codec_dev_anbernic_rgds }, 590 {}, 591 }; 592 MODULE_DEVICE_TABLE(of, aw87390_of_match); 593 594 static const struct i2c_device_id aw87390_i2c_id[] = { 595 { .name = AW87390_I2C_NAME }, 596 { .name = AW87391_I2C_NAME }, 597 { } 598 }; 599 MODULE_DEVICE_TABLE(i2c, aw87390_i2c_id); 600 601 static struct i2c_driver aw87390_i2c_driver = { 602 .driver = { 603 .name = AW87390_I2C_NAME, 604 .of_match_table = of_match_ptr(aw87390_of_match), 605 }, 606 .probe = aw87390_i2c_probe, 607 .id_table = aw87390_i2c_id, 608 }; 609 module_i2c_driver(aw87390_i2c_driver); 610 611 MODULE_DESCRIPTION("ASoC AW87390 PA Driver"); 612 MODULE_LICENSE("GPL v2"); 613