1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // AW88399 HDA side codec driver 4 // 5 // Based on cs35l41_hda.c and aw88399.c 6 // 7 8 #include <linux/acpi.h> 9 #include <linux/gpio/consumer.h> 10 #include <linux/i2c.h> 11 #include <linux/module.h> 12 #include <linux/mutex.h> 13 #include <linux/pm_runtime.h> 14 #include <linux/string.h> 15 #include <sound/hda_codec.h> 16 #include "../generic.h" 17 #include "hda_component.h" 18 #include "aw88399_hda.h" 19 20 #define AW88399_HDA_I2C_BASE_ADDR 0x34 21 22 static void aw88399_hda_playback_hook(struct device *dev, int action) 23 { 24 struct aw88399_hda *aw88399 = dev_get_drvdata(dev); 25 struct aw88399 *core = aw88399->core; 26 int ret = 0; 27 28 dev_dbg(aw88399->dev, "Playback action: %d\n", action); 29 30 switch (action) { 31 case HDA_GEN_PCM_ACT_OPEN: 32 pm_runtime_get_sync(dev); 33 aw88399->playing = true; 34 break; 35 case HDA_GEN_PCM_ACT_PREPARE: 36 if (core) 37 aw88399_start(core, AW88399_SYNC_START); 38 break; 39 case HDA_GEN_PCM_ACT_CLEANUP: 40 if (aw88399->aw_dev) 41 ret = aw88399_stop(aw88399->aw_dev); 42 if (ret) 43 dev_err(aw88399->dev, "Failed to stop amplifier: %d\n", ret); 44 break; 45 case HDA_GEN_PCM_ACT_CLOSE: 46 if (aw88399->aw_dev) 47 aw88399_stop(aw88399->aw_dev); 48 aw88399->playing = false; 49 pm_runtime_mark_last_busy(dev); 50 pm_runtime_put_autosuspend(dev); 51 break; 52 default: 53 dev_warn(aw88399->dev, "Unsupported action: %d\n", action); 54 break; 55 } 56 } 57 58 static int aw88399_hda_bind(struct device *dev, struct device *master, void *master_data) 59 { 60 struct aw88399_hda *aw88399 = dev_get_drvdata(dev); 61 struct hda_component_parent *parent = master_data; 62 struct hda_component *comp; 63 64 comp = hda_component_from_index(parent, aw88399->index); 65 if (!comp) 66 return -EINVAL; 67 68 if (comp->dev) 69 return -EBUSY; 70 71 comp->dev = dev; 72 73 strscpy(comp->name, dev_name(dev), sizeof(comp->name)); 74 75 comp->playback_hook = aw88399_hda_playback_hook; 76 77 dev_info(aw88399->dev, 78 "AW88399 Bound - SSID: %s, channel: %d\n", 79 aw88399->acpi_subsystem_id, aw88399->channel); 80 81 return 0; 82 } 83 84 static void aw88399_hda_unbind(struct device *dev, struct device *master, void *master_data) 85 { 86 struct aw88399_hda *aw88399 = dev_get_drvdata(dev); 87 struct hda_component_parent *parent = master_data; 88 struct hda_component *comp; 89 90 comp = hda_component_from_index(parent, aw88399->index); 91 if (comp && (comp->dev == dev)) 92 memset(comp, 0, sizeof(*comp)); 93 94 dev_dbg(aw88399->dev, "Unbound from HDA codec\n"); 95 } 96 97 static const struct component_ops aw88399_hda_comp_ops = { 98 .bind = aw88399_hda_bind, 99 .unbind = aw88399_hda_unbind, 100 }; 101 102 static int aw88399_hda_index_from_i2c(struct aw88399_hda *aw88399) 103 { 104 return to_i2c_client(aw88399->dev)->addr - AW88399_HDA_I2C_BASE_ADDR; 105 } 106 107 static int aw88399_hda_init(struct aw88399_hda *aw88399) 108 { 109 struct device *dev = aw88399->dev; 110 struct i2c_client *i2c = to_i2c_client(dev); 111 struct aw88399 *core; 112 int ret; 113 114 core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL); 115 if (!core) 116 return -ENOMEM; 117 118 mutex_init(&core->lock); 119 core->reset_gpio = aw88399->reset_gpio; 120 core->regmap = aw88399->regmap; 121 core->bsts_unreliable = aw88399->bsts_unreliable; 122 123 aw88399_hw_reset(core); 124 125 ret = aw88399_init(core, i2c, aw88399->regmap); 126 if (ret) 127 return ret; 128 129 /* Set channel BEFORE loading firmware so ACF parser sees correct value */ 130 if (core->aw_pa) 131 aw88399_dev_set_channel(core, aw88399->channel); 132 133 ret = aw88399_request_firmware_file(core); 134 if (ret) 135 return ret; 136 137 aw88399->core = core; 138 aw88399->aw_dev = core->aw_pa; 139 140 return 0; 141 } 142 143 static int aw88399_swap_channels(struct aw88399_hda *aw88399) 144 { 145 /* 146 * Certain Lenovo Legion laptops have their 147 * I2C wiring reversed: 0x34 is physically the right speaker, 148 * 0x35 is the left. Swap channels to correct L/R assignment. 149 * This is a model-specific hardware wiring issue, not a driver bug. 150 */ 151 aw88399->channel = 1 - aw88399->channel; 152 dev_dbg(aw88399->dev, 153 "Channel swap applied: index %d -> channel %d\n", 154 aw88399->index, aw88399->channel); 155 return 0; 156 } 157 158 static int aw88399_skip_bsts_check(struct aw88399_hda *aw88399) 159 { 160 /* 161 * BSTS (boost-finished) status bit does not reliably report on 162 * some hardware. On certain Lenovo Legion laptops, both amps 163 * report BSTS=0 (boost not finished) during normal playback 164 * despite clean audio output. Skip BSTS in the startup status 165 * check to avoid false init failures. 166 */ 167 aw88399->bsts_unreliable = true; 168 dev_dbg(aw88399->dev, "BSTS status check disabled\n"); 169 return 0; 170 } 171 172 static int aw88399_apply_legion_quirks(struct aw88399_hda *aw88399) 173 { 174 aw88399_swap_channels(aw88399); 175 aw88399_skip_bsts_check(aw88399); 176 return 0; 177 } 178 179 struct aw88399_prop_model { 180 const char *ssid; 181 int (*apply_prop)(struct aw88399_hda *aw88399); 182 }; 183 184 static const struct aw88399_prop_model aw88399_prop_model_table[] = { 185 { "17AA3906", aw88399_apply_legion_quirks }, 186 { "17AA3907", aw88399_apply_legion_quirks }, 187 { "17AA3927", aw88399_apply_legion_quirks }, 188 { "17AA3928", aw88399_apply_legion_quirks }, 189 { "17AA3936", aw88399_apply_legion_quirks }, 190 { "17AA3937", aw88399_apply_legion_quirks }, 191 { "17AA3938", aw88399_apply_legion_quirks }, 192 { "17AA3939", aw88399_apply_legion_quirks }, 193 { } 194 }; 195 196 static int aw88399_hda_acpi_probe(struct aw88399_hda *aw88399) 197 { 198 struct acpi_device *adev; 199 const char *sub; 200 const struct aw88399_prop_model *model; 201 202 aw88399->index = aw88399_hda_index_from_i2c(aw88399); 203 aw88399->channel = aw88399->index; 204 aw88399->acpi_subsystem_id = NULL; 205 206 adev = acpi_dev_get_first_match_dev("AWDZ8399", NULL, -1); 207 if (!adev) { 208 dev_err(aw88399->dev, "Failed to find an ACPI device for AWDZ8399\n"); 209 return -ENODEV; 210 } 211 212 struct device *physdev __free(put_device) = 213 get_device(acpi_get_first_physical_node(adev)); 214 acpi_dev_put(adev); 215 if (!physdev) 216 return -ENODEV; 217 218 sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); 219 if (IS_ERR_OR_NULL(sub)) 220 return 0; 221 222 aw88399->acpi_subsystem_id = devm_kstrdup(aw88399->dev, sub, GFP_KERNEL); 223 kfree(sub); 224 if (!aw88399->acpi_subsystem_id) 225 return -ENOMEM; 226 227 for (model = aw88399_prop_model_table; model->ssid; model++) { 228 if (!strcasecmp(model->ssid, aw88399->acpi_subsystem_id)) { 229 dev_info(aw88399->dev, 230 "Applying properties for SSID %s\n", 231 aw88399->acpi_subsystem_id); 232 return model->apply_prop(aw88399); 233 } 234 } 235 236 return 0; 237 } 238 239 int aw88399_hda_probe(struct device *dev, struct regmap *regmap) 240 { 241 struct aw88399_hda *aw88399; 242 int ret; 243 244 aw88399 = devm_kzalloc(dev, sizeof(*aw88399), GFP_KERNEL); 245 if (!aw88399) 246 return -ENOMEM; 247 248 if (IS_ERR(regmap)) 249 return dev_err_probe(dev, PTR_ERR(regmap), "Failed to obtain regmap\n"); 250 251 aw88399->dev = dev; 252 aw88399->regmap = regmap; 253 dev_set_drvdata(dev, aw88399); 254 255 aw88399->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 256 if (IS_ERR(aw88399->reset_gpio)) 257 return dev_err_probe(dev, PTR_ERR(aw88399->reset_gpio), 258 "Failed to get reset GPIO\n"); 259 260 ret = aw88399_hda_acpi_probe(aw88399); 261 if (ret) 262 return dev_err_probe(dev, ret, "ACPI probe failed\n"); 263 264 ret = aw88399_hda_init(aw88399); 265 if (ret) 266 return dev_err_probe(dev, ret, "Chip initialization failed\n"); 267 268 /* Enable runtime PM */ 269 pm_runtime_set_autosuspend_delay(dev, 3000); 270 pm_runtime_use_autosuspend(dev); 271 pm_runtime_mark_last_busy(dev); 272 pm_runtime_set_active(dev); 273 pm_runtime_enable(dev); 274 275 ret = component_add(dev, &aw88399_hda_comp_ops); 276 if (ret) { 277 pm_runtime_disable(dev); 278 return dev_err_probe(dev, ret, "Failed to register component\n"); 279 } 280 281 dev_info(dev, "AW88399 HDA side codec registered successfully\n"); 282 283 return 0; 284 } 285 EXPORT_SYMBOL_NS_GPL(aw88399_hda_probe, "SND_HDA_SCODEC_AW88399"); 286 287 void aw88399_hda_remove(struct device *dev) 288 { 289 struct aw88399_hda *aw88399 = dev_get_drvdata(dev); 290 291 pm_runtime_disable(dev); 292 293 if (aw88399->aw_dev) 294 aw88399_stop(aw88399->aw_dev); 295 296 component_del(dev, &aw88399_hda_comp_ops); 297 298 dev_dbg(aw88399->dev, "AW88399 HDA side codec removed\n"); 299 } 300 EXPORT_SYMBOL_NS_GPL(aw88399_hda_remove, "SND_HDA_SCODEC_AW88399"); 301 302 static int aw88399_hda_runtime_suspend(struct device *dev) 303 { 304 struct aw88399_hda *aw88399 = dev_get_drvdata(dev); 305 306 dev_dbg(aw88399->dev, "Runtime suspend\n"); 307 308 if (aw88399->aw_dev && aw88399->playing) 309 aw88399_stop(aw88399->aw_dev); 310 311 return 0; 312 } 313 314 static int aw88399_hda_runtime_resume(struct device *dev) 315 { 316 struct aw88399_hda *aw88399 = dev_get_drvdata(dev); 317 318 dev_dbg(aw88399->dev, "Runtime resume\n"); 319 320 if (aw88399->core && aw88399->aw_dev && aw88399->playing) 321 aw88399_start(aw88399->core, AW88399_SYNC_START); 322 323 return 0; 324 } 325 326 static int aw88399_hda_system_suspend(struct device *dev) 327 { 328 struct aw88399_hda *aw88399 = dev_get_drvdata(dev); 329 int ret; 330 331 dev_dbg(aw88399->dev, "System suspend\n"); 332 333 if (aw88399->aw_dev && aw88399->playing) 334 aw88399_stop(aw88399->aw_dev); 335 336 if (aw88399->core) 337 aw88399->core->fw_needs_reload = true; 338 339 ret = pm_runtime_force_suspend(dev); 340 if (ret) 341 dev_err(aw88399->dev, "Runtime force suspend failed: %d\n", ret); 342 343 return ret; 344 } 345 346 static int aw88399_hda_system_resume(struct device *dev) 347 { 348 struct aw88399_hda *aw88399 = dev_get_drvdata(dev); 349 int ret; 350 351 dev_dbg(aw88399->dev, "System resume\n"); 352 353 if (aw88399->aw_dev) 354 aw88399_hw_reset(aw88399->core); 355 356 ret = pm_runtime_force_resume(dev); 357 if (ret) 358 dev_err(aw88399->dev, "Runtime force resume failed: %d\n", ret); 359 360 return ret; 361 } 362 363 const struct dev_pm_ops aw88399_hda_pm_ops = { 364 RUNTIME_PM_OPS(aw88399_hda_runtime_suspend, aw88399_hda_runtime_resume, NULL) 365 SYSTEM_SLEEP_PM_OPS(aw88399_hda_system_suspend, aw88399_hda_system_resume) 366 }; 367 EXPORT_SYMBOL_NS_GPL(aw88399_hda_pm_ops, "SND_HDA_SCODEC_AW88399"); 368 369 MODULE_DESCRIPTION("AW88399 HDA driver"); 370 MODULE_AUTHOR("Yakov Till <yakov.till@gmail.com>"); 371 MODULE_AUTHOR("Marco Giunta <marco_giunta@outlook.it>"); 372 MODULE_LICENSE("GPL"); 373 MODULE_FIRMWARE("aw88399_acf.bin"); 374