diff options
Diffstat (limited to 'sound/soc/codecs/rt5645.c')
-rw-r--r-- | sound/soc/codecs/rt5645.c | 292 |
1 files changed, 219 insertions, 73 deletions
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index ef76940f9dcb..3e8d66661b7e 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -226,6 +226,163 @@ static const struct reg_default rt5645_reg[] = { | |||
226 | { 0xff, 0x6308 }, | 226 | { 0xff, 0x6308 }, |
227 | }; | 227 | }; |
228 | 228 | ||
229 | static const struct reg_default rt5650_reg[] = { | ||
230 | { 0x00, 0x0000 }, | ||
231 | { 0x01, 0xc8c8 }, | ||
232 | { 0x02, 0xc8c8 }, | ||
233 | { 0x03, 0xc8c8 }, | ||
234 | { 0x0a, 0x0002 }, | ||
235 | { 0x0b, 0x2827 }, | ||
236 | { 0x0c, 0xe000 }, | ||
237 | { 0x0d, 0x0000 }, | ||
238 | { 0x0e, 0x0000 }, | ||
239 | { 0x0f, 0x0808 }, | ||
240 | { 0x14, 0x3333 }, | ||
241 | { 0x16, 0x4b00 }, | ||
242 | { 0x18, 0x018b }, | ||
243 | { 0x19, 0xafaf }, | ||
244 | { 0x1a, 0xafaf }, | ||
245 | { 0x1b, 0x0001 }, | ||
246 | { 0x1c, 0x2f2f }, | ||
247 | { 0x1d, 0x2f2f }, | ||
248 | { 0x1e, 0x0000 }, | ||
249 | { 0x20, 0x0000 }, | ||
250 | { 0x27, 0x7060 }, | ||
251 | { 0x28, 0x7070 }, | ||
252 | { 0x29, 0x8080 }, | ||
253 | { 0x2a, 0x5656 }, | ||
254 | { 0x2b, 0x5454 }, | ||
255 | { 0x2c, 0xaaa0 }, | ||
256 | { 0x2d, 0x0000 }, | ||
257 | { 0x2f, 0x1002 }, | ||
258 | { 0x31, 0x5000 }, | ||
259 | { 0x32, 0x0000 }, | ||
260 | { 0x33, 0x0000 }, | ||
261 | { 0x34, 0x0000 }, | ||
262 | { 0x35, 0x0000 }, | ||
263 | { 0x3b, 0x0000 }, | ||
264 | { 0x3c, 0x007f }, | ||
265 | { 0x3d, 0x0000 }, | ||
266 | { 0x3e, 0x007f }, | ||
267 | { 0x3f, 0x0000 }, | ||
268 | { 0x40, 0x001f }, | ||
269 | { 0x41, 0x0000 }, | ||
270 | { 0x42, 0x001f }, | ||
271 | { 0x45, 0x6000 }, | ||
272 | { 0x46, 0x003e }, | ||
273 | { 0x47, 0x003e }, | ||
274 | { 0x48, 0xf807 }, | ||
275 | { 0x4a, 0x0004 }, | ||
276 | { 0x4d, 0x0000 }, | ||
277 | { 0x4e, 0x0000 }, | ||
278 | { 0x4f, 0x01ff }, | ||
279 | { 0x50, 0x0000 }, | ||
280 | { 0x51, 0x0000 }, | ||
281 | { 0x52, 0x01ff }, | ||
282 | { 0x53, 0xf000 }, | ||
283 | { 0x56, 0x0111 }, | ||
284 | { 0x57, 0x0064 }, | ||
285 | { 0x58, 0xef0e }, | ||
286 | { 0x59, 0xf0f0 }, | ||
287 | { 0x5a, 0xef0e }, | ||
288 | { 0x5b, 0xf0f0 }, | ||
289 | { 0x5c, 0xef0e }, | ||
290 | { 0x5d, 0xf0f0 }, | ||
291 | { 0x5e, 0xf000 }, | ||
292 | { 0x5f, 0x0000 }, | ||
293 | { 0x61, 0x0300 }, | ||
294 | { 0x62, 0x0000 }, | ||
295 | { 0x63, 0x00c2 }, | ||
296 | { 0x64, 0x0000 }, | ||
297 | { 0x65, 0x0000 }, | ||
298 | { 0x66, 0x0000 }, | ||
299 | { 0x6a, 0x0000 }, | ||
300 | { 0x6c, 0x0aaa }, | ||
301 | { 0x70, 0x8000 }, | ||
302 | { 0x71, 0x8000 }, | ||
303 | { 0x72, 0x8000 }, | ||
304 | { 0x73, 0x7770 }, | ||
305 | { 0x74, 0x3e00 }, | ||
306 | { 0x75, 0x2409 }, | ||
307 | { 0x76, 0x000a }, | ||
308 | { 0x77, 0x0c00 }, | ||
309 | { 0x78, 0x0000 }, | ||
310 | { 0x79, 0x0123 }, | ||
311 | { 0x7a, 0x0123 }, | ||
312 | { 0x80, 0x0000 }, | ||
313 | { 0x81, 0x0000 }, | ||
314 | { 0x82, 0x0000 }, | ||
315 | { 0x83, 0x0000 }, | ||
316 | { 0x84, 0x0000 }, | ||
317 | { 0x85, 0x0000 }, | ||
318 | { 0x8a, 0x0000 }, | ||
319 | { 0x8e, 0x0004 }, | ||
320 | { 0x8f, 0x1100 }, | ||
321 | { 0x90, 0x0646 }, | ||
322 | { 0x91, 0x0c06 }, | ||
323 | { 0x93, 0x0000 }, | ||
324 | { 0x94, 0x0200 }, | ||
325 | { 0x95, 0x0000 }, | ||
326 | { 0x9a, 0x2184 }, | ||
327 | { 0x9b, 0x010a }, | ||
328 | { 0x9c, 0x0aea }, | ||
329 | { 0x9d, 0x000c }, | ||
330 | { 0x9e, 0x0400 }, | ||
331 | { 0xa0, 0xa0a8 }, | ||
332 | { 0xa1, 0x0059 }, | ||
333 | { 0xa2, 0x0001 }, | ||
334 | { 0xae, 0x6000 }, | ||
335 | { 0xaf, 0x0000 }, | ||
336 | { 0xb0, 0x6000 }, | ||
337 | { 0xb1, 0x0000 }, | ||
338 | { 0xb2, 0x0000 }, | ||
339 | { 0xb3, 0x001f }, | ||
340 | { 0xb4, 0x020c }, | ||
341 | { 0xb5, 0x1f00 }, | ||
342 | { 0xb6, 0x0000 }, | ||
343 | { 0xbb, 0x0000 }, | ||
344 | { 0xbc, 0x0000 }, | ||
345 | { 0xbd, 0x0000 }, | ||
346 | { 0xbe, 0x0000 }, | ||
347 | { 0xbf, 0x3100 }, | ||
348 | { 0xc0, 0x0000 }, | ||
349 | { 0xc1, 0x0000 }, | ||
350 | { 0xc2, 0x0000 }, | ||
351 | { 0xc3, 0x2000 }, | ||
352 | { 0xcd, 0x0000 }, | ||
353 | { 0xce, 0x0000 }, | ||
354 | { 0xcf, 0x1813 }, | ||
355 | { 0xd0, 0x0690 }, | ||
356 | { 0xd1, 0x1c17 }, | ||
357 | { 0xd3, 0xb320 }, | ||
358 | { 0xd4, 0x0000 }, | ||
359 | { 0xd6, 0x0400 }, | ||
360 | { 0xd9, 0x0809 }, | ||
361 | { 0xda, 0x0000 }, | ||
362 | { 0xdb, 0x0003 }, | ||
363 | { 0xdc, 0x0049 }, | ||
364 | { 0xdd, 0x001b }, | ||
365 | { 0xdf, 0x0008 }, | ||
366 | { 0xe0, 0x4000 }, | ||
367 | { 0xe6, 0x8000 }, | ||
368 | { 0xe7, 0x0200 }, | ||
369 | { 0xec, 0xb300 }, | ||
370 | { 0xed, 0x0000 }, | ||
371 | { 0xf0, 0x001f }, | ||
372 | { 0xf1, 0x020c }, | ||
373 | { 0xf2, 0x1f00 }, | ||
374 | { 0xf3, 0x0000 }, | ||
375 | { 0xf4, 0x4000 }, | ||
376 | { 0xf8, 0x0000 }, | ||
377 | { 0xf9, 0x0000 }, | ||
378 | { 0xfa, 0x2060 }, | ||
379 | { 0xfb, 0x4040 }, | ||
380 | { 0xfc, 0x0000 }, | ||
381 | { 0xfd, 0x0002 }, | ||
382 | { 0xfe, 0x10ec }, | ||
383 | { 0xff, 0x6308 }, | ||
384 | }; | ||
385 | |||
229 | struct rt5645_eq_param_s { | 386 | struct rt5645_eq_param_s { |
230 | unsigned short reg; | 387 | unsigned short reg; |
231 | unsigned short val; | 388 | unsigned short val; |
@@ -572,14 +729,12 @@ static int rt5645_spk_put_volsw(struct snd_kcontrol *kcontrol, | |||
572 | struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component); | 729 | struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component); |
573 | int ret; | 730 | int ret; |
574 | 731 | ||
575 | cancel_delayed_work_sync(&rt5645->rcclock_work); | ||
576 | |||
577 | regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, | 732 | regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, |
578 | RT5645_PWR_CLK25M_MASK, RT5645_PWR_CLK25M_PU); | 733 | RT5645_PWR_CLK25M_MASK, RT5645_PWR_CLK25M_PU); |
579 | 734 | ||
580 | ret = snd_soc_put_volsw(kcontrol, ucontrol); | 735 | ret = snd_soc_put_volsw(kcontrol, ucontrol); |
581 | 736 | ||
582 | queue_delayed_work(system_power_efficient_wq, &rt5645->rcclock_work, | 737 | mod_delayed_work(system_power_efficient_wq, &rt5645->rcclock_work, |
583 | msecs_to_jiffies(200)); | 738 | msecs_to_jiffies(200)); |
584 | 739 | ||
585 | return ret; | 740 | return ret; |
@@ -3318,6 +3473,31 @@ static const struct regmap_config rt5645_regmap = { | |||
3318 | .num_ranges = ARRAY_SIZE(rt5645_ranges), | 3473 | .num_ranges = ARRAY_SIZE(rt5645_ranges), |
3319 | }; | 3474 | }; |
3320 | 3475 | ||
3476 | static const struct regmap_config rt5650_regmap = { | ||
3477 | .reg_bits = 8, | ||
3478 | .val_bits = 16, | ||
3479 | .use_single_rw = true, | ||
3480 | .max_register = RT5645_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5645_ranges) * | ||
3481 | RT5645_PR_SPACING), | ||
3482 | .volatile_reg = rt5645_volatile_register, | ||
3483 | .readable_reg = rt5645_readable_register, | ||
3484 | |||
3485 | .cache_type = REGCACHE_RBTREE, | ||
3486 | .reg_defaults = rt5650_reg, | ||
3487 | .num_reg_defaults = ARRAY_SIZE(rt5650_reg), | ||
3488 | .ranges = rt5645_ranges, | ||
3489 | .num_ranges = ARRAY_SIZE(rt5645_ranges), | ||
3490 | }; | ||
3491 | |||
3492 | static const struct regmap_config temp_regmap = { | ||
3493 | .name="nocache", | ||
3494 | .reg_bits = 8, | ||
3495 | .val_bits = 16, | ||
3496 | .use_single_rw = true, | ||
3497 | .max_register = RT5645_VENDOR_ID2 + 1, | ||
3498 | .cache_type = REGCACHE_NONE, | ||
3499 | }; | ||
3500 | |||
3321 | static const struct i2c_device_id rt5645_i2c_id[] = { | 3501 | static const struct i2c_device_id rt5645_i2c_id[] = { |
3322 | { "rt5645", 0 }, | 3502 | { "rt5645", 0 }, |
3323 | { "rt5650", 0 }, | 3503 | { "rt5650", 0 }, |
@@ -3334,69 +3514,23 @@ static struct acpi_device_id rt5645_acpi_match[] = { | |||
3334 | MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match); | 3514 | MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match); |
3335 | #endif | 3515 | #endif |
3336 | 3516 | ||
3337 | static struct rt5645_platform_data *rt5645_pdata; | 3517 | static struct rt5645_platform_data general_platform_data = { |
3338 | |||
3339 | static struct rt5645_platform_data strago_platform_data = { | ||
3340 | .dmic1_data_pin = RT5645_DMIC1_DISABLE, | 3518 | .dmic1_data_pin = RT5645_DMIC1_DISABLE, |
3341 | .dmic2_data_pin = RT5645_DMIC_DATA_IN2P, | 3519 | .dmic2_data_pin = RT5645_DMIC_DATA_IN2P, |
3342 | .jd_mode = 3, | 3520 | .jd_mode = 3, |
3343 | }; | 3521 | }; |
3344 | 3522 | ||
3345 | static int strago_quirk_cb(const struct dmi_system_id *id) | ||
3346 | { | ||
3347 | rt5645_pdata = &strago_platform_data; | ||
3348 | |||
3349 | return 1; | ||
3350 | } | ||
3351 | |||
3352 | static const struct dmi_system_id dmi_platform_intel_braswell[] = { | 3523 | static const struct dmi_system_id dmi_platform_intel_braswell[] = { |
3353 | { | 3524 | { |
3354 | .ident = "Intel Strago", | 3525 | .ident = "Intel Strago", |
3355 | .callback = strago_quirk_cb, | ||
3356 | .matches = { | 3526 | .matches = { |
3357 | DMI_MATCH(DMI_PRODUCT_NAME, "Strago"), | 3527 | DMI_MATCH(DMI_PRODUCT_NAME, "Strago"), |
3358 | }, | 3528 | }, |
3359 | }, | 3529 | }, |
3360 | { | 3530 | { |
3361 | .ident = "Google Celes", | 3531 | .ident = "Google Chrome", |
3362 | .callback = strago_quirk_cb, | ||
3363 | .matches = { | ||
3364 | DMI_MATCH(DMI_PRODUCT_NAME, "Celes"), | ||
3365 | }, | ||
3366 | }, | ||
3367 | { | ||
3368 | .ident = "Google Ultima", | ||
3369 | .callback = strago_quirk_cb, | ||
3370 | .matches = { | ||
3371 | DMI_MATCH(DMI_PRODUCT_NAME, "Ultima"), | ||
3372 | }, | ||
3373 | }, | ||
3374 | { | ||
3375 | .ident = "Google Reks", | ||
3376 | .callback = strago_quirk_cb, | ||
3377 | .matches = { | ||
3378 | DMI_MATCH(DMI_PRODUCT_NAME, "Reks"), | ||
3379 | }, | ||
3380 | }, | ||
3381 | { | ||
3382 | .ident = "Google Edgar", | ||
3383 | .callback = strago_quirk_cb, | ||
3384 | .matches = { | ||
3385 | DMI_MATCH(DMI_PRODUCT_NAME, "Edgar"), | ||
3386 | }, | ||
3387 | }, | ||
3388 | { | ||
3389 | .ident = "Google Wizpig", | ||
3390 | .callback = strago_quirk_cb, | ||
3391 | .matches = { | ||
3392 | DMI_MATCH(DMI_PRODUCT_NAME, "Wizpig"), | ||
3393 | }, | ||
3394 | }, | ||
3395 | { | ||
3396 | .ident = "Google Terra", | ||
3397 | .callback = strago_quirk_cb, | ||
3398 | .matches = { | 3532 | .matches = { |
3399 | DMI_MATCH(DMI_PRODUCT_NAME, "Terra"), | 3533 | DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), |
3400 | }, | 3534 | }, |
3401 | }, | 3535 | }, |
3402 | { } | 3536 | { } |
@@ -3409,17 +3543,9 @@ static struct rt5645_platform_data buddy_platform_data = { | |||
3409 | .jd_invert = true, | 3543 | .jd_invert = true, |
3410 | }; | 3544 | }; |
3411 | 3545 | ||
3412 | static int buddy_quirk_cb(const struct dmi_system_id *id) | ||
3413 | { | ||
3414 | rt5645_pdata = &buddy_platform_data; | ||
3415 | |||
3416 | return 1; | ||
3417 | } | ||
3418 | |||
3419 | static struct dmi_system_id dmi_platform_intel_broadwell[] = { | 3546 | static struct dmi_system_id dmi_platform_intel_broadwell[] = { |
3420 | { | 3547 | { |
3421 | .ident = "Chrome Buddy", | 3548 | .ident = "Chrome Buddy", |
3422 | .callback = buddy_quirk_cb, | ||
3423 | .matches = { | 3549 | .matches = { |
3424 | DMI_MATCH(DMI_PRODUCT_NAME, "Buddy"), | 3550 | DMI_MATCH(DMI_PRODUCT_NAME, "Buddy"), |
3425 | }, | 3551 | }, |
@@ -3427,6 +3553,16 @@ static struct dmi_system_id dmi_platform_intel_broadwell[] = { | |||
3427 | { } | 3553 | { } |
3428 | }; | 3554 | }; |
3429 | 3555 | ||
3556 | static bool rt5645_check_dp(struct device *dev) | ||
3557 | { | ||
3558 | if (device_property_present(dev, "realtek,in2-differential") || | ||
3559 | device_property_present(dev, "realtek,dmic1-data-pin") || | ||
3560 | device_property_present(dev, "realtek,dmic2-data-pin") || | ||
3561 | device_property_present(dev, "realtek,jd-mode")) | ||
3562 | return true; | ||
3563 | |||
3564 | return false; | ||
3565 | } | ||
3430 | 3566 | ||
3431 | static int rt5645_parse_dt(struct rt5645_priv *rt5645, struct device *dev) | 3567 | static int rt5645_parse_dt(struct rt5645_priv *rt5645, struct device *dev) |
3432 | { | 3568 | { |
@@ -3449,6 +3585,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3449 | struct rt5645_priv *rt5645; | 3585 | struct rt5645_priv *rt5645; |
3450 | int ret, i; | 3586 | int ret, i; |
3451 | unsigned int val; | 3587 | unsigned int val; |
3588 | struct regmap *regmap; | ||
3452 | 3589 | ||
3453 | rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv), | 3590 | rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv), |
3454 | GFP_KERNEL); | 3591 | GFP_KERNEL); |
@@ -3460,11 +3597,12 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3460 | 3597 | ||
3461 | if (pdata) | 3598 | if (pdata) |
3462 | rt5645->pdata = *pdata; | 3599 | rt5645->pdata = *pdata; |
3463 | else if (dmi_check_system(dmi_platform_intel_braswell) || | 3600 | else if (dmi_check_system(dmi_platform_intel_broadwell)) |
3464 | dmi_check_system(dmi_platform_intel_broadwell)) | 3601 | rt5645->pdata = buddy_platform_data; |
3465 | rt5645->pdata = *rt5645_pdata; | 3602 | else if (rt5645_check_dp(&i2c->dev)) |
3466 | else | ||
3467 | rt5645_parse_dt(rt5645, &i2c->dev); | 3603 | rt5645_parse_dt(rt5645, &i2c->dev); |
3604 | else if (dmi_check_system(dmi_platform_intel_braswell)) | ||
3605 | rt5645->pdata = general_platform_data; | ||
3468 | 3606 | ||
3469 | rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect", | 3607 | rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect", |
3470 | GPIOD_IN); | 3608 | GPIOD_IN); |
@@ -3474,14 +3612,6 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3474 | return PTR_ERR(rt5645->gpiod_hp_det); | 3612 | return PTR_ERR(rt5645->gpiod_hp_det); |
3475 | } | 3613 | } |
3476 | 3614 | ||
3477 | rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap); | ||
3478 | if (IS_ERR(rt5645->regmap)) { | ||
3479 | ret = PTR_ERR(rt5645->regmap); | ||
3480 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
3481 | ret); | ||
3482 | return ret; | ||
3483 | } | ||
3484 | |||
3485 | for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++) | 3615 | for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++) |
3486 | rt5645->supplies[i].supply = rt5645_supply_names[i]; | 3616 | rt5645->supplies[i].supply = rt5645_supply_names[i]; |
3487 | 3617 | ||
@@ -3500,13 +3630,22 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3500 | return ret; | 3630 | return ret; |
3501 | } | 3631 | } |
3502 | 3632 | ||
3503 | regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val); | 3633 | regmap = devm_regmap_init_i2c(i2c, &temp_regmap); |
3634 | if (IS_ERR(regmap)) { | ||
3635 | ret = PTR_ERR(regmap); | ||
3636 | dev_err(&i2c->dev, "Failed to allocate temp register map: %d\n", | ||
3637 | ret); | ||
3638 | return ret; | ||
3639 | } | ||
3640 | regmap_read(regmap, RT5645_VENDOR_ID2, &val); | ||
3504 | 3641 | ||
3505 | switch (val) { | 3642 | switch (val) { |
3506 | case RT5645_DEVICE_ID: | 3643 | case RT5645_DEVICE_ID: |
3644 | rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap); | ||
3507 | rt5645->codec_type = CODEC_TYPE_RT5645; | 3645 | rt5645->codec_type = CODEC_TYPE_RT5645; |
3508 | break; | 3646 | break; |
3509 | case RT5650_DEVICE_ID: | 3647 | case RT5650_DEVICE_ID: |
3648 | rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5650_regmap); | ||
3510 | rt5645->codec_type = CODEC_TYPE_RT5650; | 3649 | rt5645->codec_type = CODEC_TYPE_RT5650; |
3511 | break; | 3650 | break; |
3512 | default: | 3651 | default: |
@@ -3517,6 +3656,13 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3517 | goto err_enable; | 3656 | goto err_enable; |
3518 | } | 3657 | } |
3519 | 3658 | ||
3659 | if (IS_ERR(rt5645->regmap)) { | ||
3660 | ret = PTR_ERR(rt5645->regmap); | ||
3661 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
3662 | ret); | ||
3663 | return ret; | ||
3664 | } | ||
3665 | |||
3520 | regmap_write(rt5645->regmap, RT5645_RESET, 0); | 3666 | regmap_write(rt5645->regmap, RT5645_RESET, 0); |
3521 | 3667 | ||
3522 | ret = regmap_register_patch(rt5645->regmap, init_list, | 3668 | ret = regmap_register_patch(rt5645->regmap, init_list, |