Skip to content

Commit afe66ef

Browse files
Ernest Van Hoeckebroonie
authored andcommitted
ASoC: wm8904: get platform data from DT
Read in optional codec-specific properties from the device tree. The platform_data structure is not populated when using device trees. This change parses optional dts properties to populate it. - wlf,in1l-as-dmicdat1 - wlf,in1r-as-dmicdat2 - wlf,gpio-cfg - wlf,micbias-cfg - wlf,drc-cfg-regs - wlf,drc-cfg-names - wlf,retune-mobile-cfg-regs - wlf,retune-mobile-cfg-names - wlf,retune-mobile-cfg-hz Datasheet: https://statics.cirrus.com/pubs/proDatasheet/WM8904_Rev4.1.pdf Signed-off-by: Ernest Van Hoecke <ernest.vanhoecke@toradex.com> Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com> Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com> Link: https://patch.msgid.link/20250319142059.46692-5-francesco@dolcini.it Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent bd552e9 commit afe66ef

File tree

2 files changed

+191
-1
lines changed

2 files changed

+191
-1
lines changed

include/sound/wm8904.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ struct wm8904_pdata {
151151
int num_retune_mobile_cfgs;
152152
struct wm8904_retune_mobile_cfg *retune_mobile_cfgs;
153153

154+
bool in1l_as_dmicdat1;
155+
bool in1r_as_dmicdat2;
156+
154157
u32 gpio_cfg[WM8904_GPIO_REGS];
155158
u32 mic_cfg[WM8904_MIC_REGS];
156159
};

sound/soc/codecs/wm8904.c

Lines changed: 188 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2168,6 +2168,184 @@ static const struct of_device_id wm8904_of_match[] = {
21682168
MODULE_DEVICE_TABLE(of, wm8904_of_match);
21692169
#endif
21702170

2171+
/**
2172+
* wm8904_read_cfg_reg_arr() - Reads a subarray from a DT u16 array
2173+
*
2174+
* @np: pointer to the device_node struct
2175+
* @regs_property: DT property of interest
2176+
* @size: size of subarrays within the array
2177+
* @idx: index of the subarray of interest
2178+
* @out: output
2179+
*
2180+
* Helper to read a subarray from a DT uint16-array,
2181+
* divided into equally sized arrays of size `size`
2182+
*
2183+
* Subset starts at `idx * size` and is of size `size`
2184+
*
2185+
* Return: 0 on success, negative error code otherwise
2186+
*/
2187+
static int wm8904_read_cfg_reg_arr(const struct device_node *np,
2188+
const char * const regs_property,
2189+
int size, int idx,
2190+
u16 * const out)
2191+
{
2192+
int i, offset, ret;
2193+
2194+
offset = idx * size;
2195+
2196+
for (i = 0; i < size; i++) {
2197+
ret = of_property_read_u16_index(np, regs_property, i + offset, &out[i]);
2198+
if (ret)
2199+
return ret;
2200+
}
2201+
return 0;
2202+
}
2203+
2204+
static int wm8904_parse_retune_cfg_regs(const struct device_node *np,
2205+
struct wm8904_pdata *pdata, int cfg_idx)
2206+
{
2207+
return wm8904_read_cfg_reg_arr(np, "wlf,retune-mobile-cfg-regs",
2208+
WM8904_EQ_REGS, cfg_idx,
2209+
&pdata->retune_mobile_cfgs[cfg_idx].regs[0]);
2210+
}
2211+
2212+
static int wm8904_parse_drc_cfg_regs(const struct device_node *np,
2213+
struct wm8904_pdata *pdata, int cfg_idx)
2214+
{
2215+
return wm8904_read_cfg_reg_arr(np, "wlf,drc-cfg-regs",
2216+
WM8904_DRC_REGS, cfg_idx,
2217+
&pdata->drc_cfgs[cfg_idx].regs[0]);
2218+
}
2219+
2220+
static int wm8904_parse_drc_cfg_from_of(struct i2c_client *i2c,
2221+
struct wm8904_pdata *pdata)
2222+
{
2223+
const struct device_node *np = i2c->dev.of_node;
2224+
int i, n_cfgs;
2225+
2226+
n_cfgs = of_property_count_strings(np, "wlf,drc-cfg-names");
2227+
if (n_cfgs == -EINVAL)
2228+
return 0;
2229+
2230+
if (n_cfgs <= 0) {
2231+
dev_err(&i2c->dev, "Could not get wlf,drc-cfg-names length: %d",
2232+
n_cfgs);
2233+
return n_cfgs;
2234+
}
2235+
2236+
pdata->drc_cfgs = devm_kzalloc(&i2c->dev,
2237+
n_cfgs * sizeof(struct wm8904_drc_cfg),
2238+
GFP_KERNEL);
2239+
if (!pdata->drc_cfgs)
2240+
return -ENOMEM;
2241+
2242+
for (i = 0; i < n_cfgs; i++) {
2243+
if (wm8904_parse_drc_cfg_regs(np, pdata, i)) {
2244+
dev_err(&i2c->dev,
2245+
"Invalid 'wlf,drc-cfg-regs[%i,:]'\n", i);
2246+
return -EINVAL;
2247+
}
2248+
2249+
if (of_property_read_string_index(np, "wlf,drc-cfg-names", i,
2250+
&pdata->drc_cfgs[i].name)) {
2251+
dev_err(&i2c->dev,
2252+
"Invalid 'wlf,drc-cfg-names[%i]'\n", i);
2253+
return -EINVAL;
2254+
}
2255+
}
2256+
2257+
pdata->num_drc_cfgs = n_cfgs;
2258+
return 0;
2259+
}
2260+
2261+
static int wm8904_parse_retune_cfg_from_of(struct i2c_client *i2c,
2262+
struct wm8904_pdata *pdata)
2263+
{
2264+
const struct device_node *np = i2c->dev.of_node;
2265+
int i, n_cfgs;
2266+
2267+
n_cfgs = of_property_count_strings(np, "wlf,retune-mobile-cfg-names");
2268+
if (n_cfgs == -EINVAL)
2269+
return 0;
2270+
2271+
if (n_cfgs <= 0) {
2272+
dev_err(&i2c->dev,
2273+
"Could not get wlf,retune-mobile-cfg-names length: %d",
2274+
n_cfgs);
2275+
return n_cfgs;
2276+
}
2277+
2278+
pdata->retune_mobile_cfgs = devm_kzalloc(&i2c->dev,
2279+
n_cfgs * sizeof(struct wm8904_retune_mobile_cfg),
2280+
GFP_KERNEL);
2281+
if (!pdata->retune_mobile_cfgs)
2282+
return -ENOMEM;
2283+
2284+
for (i = 0; i < n_cfgs; i++) {
2285+
if (wm8904_parse_retune_cfg_regs(np, pdata, i)) {
2286+
dev_err(&i2c->dev,
2287+
"Invalid 'wlf,retune-mobile-cfg-regs[%i,:]'\n", i);
2288+
return -EINVAL;
2289+
}
2290+
2291+
if (of_property_read_u32_index(np, "wlf,retune-mobile-cfg-hz", i,
2292+
&pdata->retune_mobile_cfgs[i].rate)) {
2293+
dev_err(&i2c->dev,
2294+
"Invalid 'wlf,retune-mobile-cfg-hz[%i]'\n", i);
2295+
return -EINVAL;
2296+
}
2297+
2298+
if (of_property_read_string_index(np, "wlf,retune-mobile-cfg-names", i,
2299+
&pdata->retune_mobile_cfgs[i].name)) {
2300+
dev_err(&i2c->dev,
2301+
"Invalid 'wlf,retune-mobile-cfg-names[%i]'\n", i);
2302+
return -EINVAL;
2303+
}
2304+
}
2305+
2306+
pdata->num_retune_mobile_cfgs = n_cfgs;
2307+
return 0;
2308+
}
2309+
2310+
static int wm8904_set_pdata_from_of(struct i2c_client *i2c,
2311+
struct wm8904_priv *wm8904)
2312+
{
2313+
const struct device_node *np = i2c->dev.of_node;
2314+
struct wm8904_pdata *pdata;
2315+
int ret, i;
2316+
2317+
pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
2318+
if (!pdata)
2319+
return -ENOMEM;
2320+
2321+
pdata->in1l_as_dmicdat1 =
2322+
of_property_read_bool(np, "wlf,in1l-as-dmicdat1");
2323+
2324+
pdata->in1r_as_dmicdat2 =
2325+
of_property_read_bool(np, "wlf,in1r-as-dmicdat2");
2326+
2327+
/* If absent, default to 0xFFFF for GPIO config (i.e.: don't set) */
2328+
for (i = 0; i < WM8904_GPIO_REGS; i++)
2329+
pdata->gpio_cfg[i] = 0xFFFF;
2330+
2331+
of_property_read_u32_array(np, "wlf,gpio-cfg", pdata->gpio_cfg,
2332+
ARRAY_SIZE(pdata->gpio_cfg));
2333+
2334+
of_property_read_u32_array(np, "wlf,micbias-cfg", pdata->mic_cfg,
2335+
ARRAY_SIZE(pdata->mic_cfg));
2336+
2337+
ret = wm8904_parse_drc_cfg_from_of(i2c, pdata);
2338+
if (ret)
2339+
return ret;
2340+
2341+
ret = wm8904_parse_retune_cfg_from_of(i2c, pdata);
2342+
if (ret)
2343+
return ret;
2344+
2345+
wm8904->pdata = pdata;
2346+
return 0;
2347+
}
2348+
21712349
static const struct i2c_device_id wm8904_i2c_id[];
21722350

21732351
static int wm8904_i2c_probe(struct i2c_client *i2c)
@@ -2199,7 +2377,16 @@ static int wm8904_i2c_probe(struct i2c_client *i2c)
21992377
wm8904->devtype = (uintptr_t)i2c_get_match_data(i2c);
22002378

22012379
i2c_set_clientdata(i2c, wm8904);
2202-
wm8904->pdata = i2c->dev.platform_data;
2380+
2381+
if (i2c->dev.of_node) {
2382+
ret = wm8904_set_pdata_from_of(i2c, wm8904);
2383+
if (ret) {
2384+
dev_err(&i2c->dev, "Failed to set platform data from of: %d\n", ret);
2385+
return ret;
2386+
}
2387+
} else {
2388+
wm8904->pdata = i2c->dev.platform_data;
2389+
}
22032390

22042391
for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++)
22052392
wm8904->supplies[i].supply = wm8904_supply_names[i];

0 commit comments

Comments
 (0)