@@ -2168,6 +2168,184 @@ static const struct of_device_id wm8904_of_match[] = {
21682168MODULE_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+
21712349static const struct i2c_device_id wm8904_i2c_id [];
21722350
21732351static 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