1 /* 2 * Renesas R-Car Gen1 SRU/SSI support 3 * 4 * Copyright (C) 2013 Renesas Solutions Corp. 5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 #include "rsnd.h" 12 13 struct rsnd_gen { 14 void __iomem *base[RSND_BASE_MAX]; 15 16 struct rsnd_gen_ops *ops; 17 18 struct regmap *regmap; 19 struct regmap_field *regs[RSND_REG_MAX]; 20 }; 21 22 #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) 23 24 #define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \ 25 [id] = { \ 26 .reg = (unsigned int)gen->base[reg_id] + offset, \ 27 .lsb = 0, \ 28 .msb = 31, \ 29 .id_size = _id_size, \ 30 .id_offset = _id_offset, \ 31 } 32 33 /* 34 * basic function 35 */ 36 static int rsnd_regmap_write32(void *context, const void *_data, size_t count) 37 { 38 struct rsnd_priv *priv = context; 39 struct device *dev = rsnd_priv_to_dev(priv); 40 u32 *data = (u32 *)_data; 41 u32 val = data[1]; 42 void __iomem *reg = (void *)data[0]; 43 44 iowrite32(val, reg); 45 46 dev_dbg(dev, "w %p : %08x\n", reg, val); 47 48 return 0; 49 } 50 51 static int rsnd_regmap_read32(void *context, 52 const void *_data, size_t reg_size, 53 void *_val, size_t val_size) 54 { 55 struct rsnd_priv *priv = context; 56 struct device *dev = rsnd_priv_to_dev(priv); 57 u32 *data = (u32 *)_data; 58 u32 *val = (u32 *)_val; 59 void __iomem *reg = (void *)data[0]; 60 61 *val = ioread32(reg); 62 63 dev_dbg(dev, "r %p : %08x\n", reg, *val); 64 65 return 0; 66 } 67 68 static struct regmap_bus rsnd_regmap_bus = { 69 .write = rsnd_regmap_write32, 70 .read = rsnd_regmap_read32, 71 .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, 72 .val_format_endian_default = REGMAP_ENDIAN_NATIVE, 73 }; 74 75 static int rsnd_is_accessible_reg(struct rsnd_priv *priv, 76 struct rsnd_gen *gen, enum rsnd_reg reg) 77 { 78 if (!gen->regs[reg]) { 79 struct device *dev = rsnd_priv_to_dev(priv); 80 81 dev_err(dev, "unsupported register access %x\n", reg); 82 return 0; 83 } 84 85 return 1; 86 } 87 88 u32 rsnd_read(struct rsnd_priv *priv, 89 struct rsnd_mod *mod, enum rsnd_reg reg) 90 { 91 struct rsnd_gen *gen = rsnd_priv_to_gen(priv); 92 u32 val; 93 94 if (!rsnd_is_accessible_reg(priv, gen, reg)) 95 return 0; 96 97 regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); 98 99 return val; 100 } 101 102 void rsnd_write(struct rsnd_priv *priv, 103 struct rsnd_mod *mod, 104 enum rsnd_reg reg, u32 data) 105 { 106 struct rsnd_gen *gen = rsnd_priv_to_gen(priv); 107 108 if (!rsnd_is_accessible_reg(priv, gen, reg)) 109 return; 110 111 regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); 112 } 113 114 void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, 115 enum rsnd_reg reg, u32 mask, u32 data) 116 { 117 struct rsnd_gen *gen = rsnd_priv_to_gen(priv); 118 119 if (!rsnd_is_accessible_reg(priv, gen, reg)) 120 return; 121 122 regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), 123 mask, data); 124 } 125 126 static int rsnd_gen_regmap_init(struct rsnd_priv *priv, 127 struct rsnd_gen *gen, 128 struct reg_field *regf) 129 { 130 int i; 131 struct device *dev = rsnd_priv_to_dev(priv); 132 struct regmap_config regc; 133 134 memset(®c, 0, sizeof(regc)); 135 regc.reg_bits = 32; 136 regc.val_bits = 32; 137 138 gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, ®c); 139 if (IS_ERR(gen->regmap)) { 140 dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap)); 141 return PTR_ERR(gen->regmap); 142 } 143 144 for (i = 0; i < RSND_REG_MAX; i++) { 145 gen->regs[i] = NULL; 146 if (!regf[i].reg) 147 continue; 148 149 gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]); 150 if (IS_ERR(gen->regs[i])) 151 return PTR_ERR(gen->regs[i]); 152 153 } 154 155 return 0; 156 } 157 158 /* 159 * DMA read/write register offset 160 * 161 * RSND_xxx_I_N for Audio DMAC input 162 * RSND_xxx_O_N for Audio DMAC output 163 * RSND_xxx_I_P for Audio DMAC peri peri input 164 * RSND_xxx_O_P for Audio DMAC peri peri output 165 * 166 * ex) R-Car H2 case 167 * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out 168 * SSI : 0xec541000 / 0xec241008 / 0xec24100c / 0xec400000 / 0xec400000 169 * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 170 * CMD : 0xec500000 / 0xec008000 0xec308000 171 */ 172 #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) 173 #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) 174 175 #define RDMA_SSI_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) 176 #define RDMA_SSI_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) 177 178 #define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) 179 #define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) 180 181 #define RDMA_SRC_I_P(addr, i) (addr ##_reg - 0x00200000 + (0x400 * i)) 182 #define RDMA_SRC_O_P(addr, i) (addr ##_reg - 0x001fc000 + (0x400 * i)) 183 184 #define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) 185 #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) 186 187 void rsnd_gen_dma_addr(struct rsnd_priv *priv, 188 struct rsnd_dma *dma, 189 struct dma_slave_config *cfg, 190 int is_play, int slave_id) 191 { 192 struct platform_device *pdev = rsnd_priv_to_pdev(priv); 193 struct device *dev = rsnd_priv_to_dev(priv); 194 struct rsnd_mod *mod = rsnd_dma_to_mod(dma); 195 struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 196 dma_addr_t ssi_reg = platform_get_resource(pdev, 197 IORESOURCE_MEM, RSND_GEN2_SSI)->start; 198 dma_addr_t src_reg = platform_get_resource(pdev, 199 IORESOURCE_MEM, RSND_GEN2_SCU)->start; 200 int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); 201 int use_src = !!rsnd_io_to_mod_src(io); 202 int use_dvc = !!rsnd_io_to_mod_dvc(io); 203 int id = rsnd_mod_id(mod); 204 struct dma_addr { 205 dma_addr_t src_addr; 206 dma_addr_t dst_addr; 207 } dma_addrs[2][2][3] = { 208 { /* SRC */ 209 /* Capture */ 210 {{ 0, 0 }, 211 { RDMA_SRC_O_N(src, id), 0 }, 212 { RDMA_CMD_O_N(src, id), 0 }}, 213 /* Playback */ 214 {{ 0, 0, }, 215 { 0, RDMA_SRC_I_N(src, id) }, 216 { 0, RDMA_SRC_I_N(src, id) }} 217 }, { /* SSI */ 218 /* Capture */ 219 {{ RDMA_SSI_O_N(ssi, id), 0 }, 220 { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }, 221 { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }}, 222 /* Playback */ 223 {{ 0, RDMA_SSI_I_N(ssi, id) }, 224 { RDMA_SRC_O_P(src, id), RDMA_SSI_I_P(ssi, id) }, 225 { RDMA_CMD_O_P(src, id), RDMA_SSI_I_P(ssi, id) }} 226 } 227 }; 228 229 cfg->slave_id = slave_id; 230 cfg->src_addr = 0; 231 cfg->dst_addr = 0; 232 cfg->direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; 233 234 /* 235 * gen1 uses default DMA addr 236 */ 237 if (rsnd_is_gen1(priv)) 238 return; 239 240 /* it shouldn't happen */ 241 if (use_dvc & !use_src) { 242 dev_err(dev, "DVC is selected without SRC\n"); 243 return; 244 } 245 246 cfg->src_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].src_addr; 247 cfg->dst_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].dst_addr; 248 249 dev_dbg(dev, "dma%d addr - src : %x / dst : %x\n", 250 id, cfg->src_addr, cfg->dst_addr); 251 } 252 253 /* 254 * Gen2 255 */ 256 257 /* single address mapping */ 258 #define RSND_GEN2_S_REG(gen, reg, id, offset) \ 259 RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10) 260 261 /* multi address mapping */ 262 #define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset) \ 263 RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10) 264 265 static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) 266 { 267 struct reg_field regf[RSND_REG_MAX] = { 268 RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), 269 RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), 270 /* FIXME: it needs SSI_MODE2/3 in the future */ 271 RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), 272 RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), 273 RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), 274 RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), 275 276 RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), 277 RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), 278 RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), 279 RSND_GEN2_M_REG(gen, SCU, CMD_ROUTE_SLCT, 0x18c, 0x20), 280 RSND_GEN2_M_REG(gen, SCU, CMD_CTRL, 0x190, 0x20), 281 RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), 282 RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), 283 RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), 284 RSND_GEN2_M_REG(gen, SCU, SRC_IFSCR, 0x21c, 0x40), 285 RSND_GEN2_M_REG(gen, SCU, SRC_IFSVR, 0x220, 0x40), 286 RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), 287 RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), 288 RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), 289 RSND_GEN2_M_REG(gen, SCU, DVC_SWRSR, 0xe00, 0x100), 290 RSND_GEN2_M_REG(gen, SCU, DVC_DVUIR, 0xe04, 0x100), 291 RSND_GEN2_M_REG(gen, SCU, DVC_ADINR, 0xe08, 0x100), 292 RSND_GEN2_M_REG(gen, SCU, DVC_DVUCR, 0xe10, 0x100), 293 RSND_GEN2_M_REG(gen, SCU, DVC_ZCMCR, 0xe14, 0x100), 294 RSND_GEN2_M_REG(gen, SCU, DVC_VOL0R, 0xe28, 0x100), 295 RSND_GEN2_M_REG(gen, SCU, DVC_VOL1R, 0xe2c, 0x100), 296 RSND_GEN2_M_REG(gen, SCU, DVC_DVUER, 0xe48, 0x100), 297 298 RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), 299 RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), 300 RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), 301 RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), 302 RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), 303 RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), 304 RSND_GEN2_S_REG(gen, ADG, DIV_EN, 0x30), 305 RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), 306 RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), 307 RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), 308 RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL3, 0x40), 309 RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL4, 0x44), 310 RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL0, 0x48), 311 RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL1, 0x4c), 312 RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), 313 RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), 314 RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), 315 RSND_GEN2_S_REG(gen, ADG, CMDOUT_TIMSEL, 0x5c), 316 317 RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), 318 RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), 319 RSND_GEN2_M_REG(gen, SSI, SSITDR, 0x08, 0x40), 320 RSND_GEN2_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), 321 RSND_GEN2_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), 322 }; 323 324 return rsnd_gen_regmap_init(priv, gen, regf); 325 } 326 327 static int rsnd_gen2_probe(struct platform_device *pdev, 328 struct rsnd_priv *priv) 329 { 330 struct device *dev = rsnd_priv_to_dev(priv); 331 struct rsnd_gen *gen = rsnd_priv_to_gen(priv); 332 struct resource *scu_res; 333 struct resource *adg_res; 334 struct resource *ssiu_res; 335 struct resource *ssi_res; 336 int ret; 337 338 /* 339 * map address 340 */ 341 scu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SCU); 342 adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_ADG); 343 ssiu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSIU); 344 ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSI); 345 346 gen->base[RSND_GEN2_SCU] = devm_ioremap_resource(dev, scu_res); 347 gen->base[RSND_GEN2_ADG] = devm_ioremap_resource(dev, adg_res); 348 gen->base[RSND_GEN2_SSIU] = devm_ioremap_resource(dev, ssiu_res); 349 gen->base[RSND_GEN2_SSI] = devm_ioremap_resource(dev, ssi_res); 350 if (IS_ERR(gen->base[RSND_GEN2_SCU]) || 351 IS_ERR(gen->base[RSND_GEN2_ADG]) || 352 IS_ERR(gen->base[RSND_GEN2_SSIU]) || 353 IS_ERR(gen->base[RSND_GEN2_SSI])) 354 return -ENODEV; 355 356 ret = rsnd_gen2_regmap_init(priv, gen); 357 if (ret < 0) 358 return ret; 359 360 dev_dbg(dev, "Gen2 device probed\n"); 361 dev_dbg(dev, "SCU : %pap => %p\n", &scu_res->start, 362 gen->base[RSND_GEN2_SCU]); 363 dev_dbg(dev, "ADG : %pap => %p\n", &adg_res->start, 364 gen->base[RSND_GEN2_ADG]); 365 dev_dbg(dev, "SSIU : %pap => %p\n", &ssiu_res->start, 366 gen->base[RSND_GEN2_SSIU]); 367 dev_dbg(dev, "SSI : %pap => %p\n", &ssi_res->start, 368 gen->base[RSND_GEN2_SSI]); 369 370 return 0; 371 } 372 373 /* 374 * Gen1 375 */ 376 377 /* single address mapping */ 378 #define RSND_GEN1_S_REG(gen, reg, id, offset) \ 379 RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9) 380 381 /* multi address mapping */ 382 #define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \ 383 RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9) 384 385 static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) 386 { 387 struct reg_field regf[RSND_REG_MAX] = { 388 RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_SEL, 0x00), 389 RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08), 390 RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL1, 0x0c), 391 RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL2, 0x10), 392 RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_CTRL, 0xc0), 393 RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), 394 RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), 395 RSND_GEN1_M_REG(gen, SRU, SRC_BUSIF_MODE, 0x20, 0x4), 396 RSND_GEN1_M_REG(gen, SRU, SRC_ROUTE_MODE0,0x50, 0x8), 397 RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), 398 RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), 399 RSND_GEN1_M_REG(gen, SRU, SRC_ADINR, 0x214, 0x40), 400 RSND_GEN1_M_REG(gen, SRU, SRC_IFSCR, 0x21c, 0x40), 401 RSND_GEN1_M_REG(gen, SRU, SRC_IFSVR, 0x220, 0x40), 402 RSND_GEN1_M_REG(gen, SRU, SRC_SRCCR, 0x224, 0x40), 403 RSND_GEN1_M_REG(gen, SRU, SRC_MNFSR, 0x228, 0x40), 404 405 RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00), 406 RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04), 407 RSND_GEN1_S_REG(gen, ADG, SSICKR, 0x08), 408 RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), 409 RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), 410 RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL3, 0x18), 411 RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL4, 0x1c), 412 RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL5, 0x20), 413 414 RSND_GEN1_M_REG(gen, SSI, SSICR, 0x00, 0x40), 415 RSND_GEN1_M_REG(gen, SSI, SSISR, 0x04, 0x40), 416 RSND_GEN1_M_REG(gen, SSI, SSITDR, 0x08, 0x40), 417 RSND_GEN1_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), 418 RSND_GEN1_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), 419 }; 420 421 return rsnd_gen_regmap_init(priv, gen, regf); 422 } 423 424 static int rsnd_gen1_probe(struct platform_device *pdev, 425 struct rsnd_priv *priv) 426 { 427 struct device *dev = rsnd_priv_to_dev(priv); 428 struct rsnd_gen *gen = rsnd_priv_to_gen(priv); 429 struct resource *sru_res; 430 struct resource *adg_res; 431 struct resource *ssi_res; 432 int ret; 433 434 /* 435 * map address 436 */ 437 sru_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU); 438 adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG); 439 ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SSI); 440 441 gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res); 442 gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res); 443 gen->base[RSND_GEN1_SSI] = devm_ioremap_resource(dev, ssi_res); 444 if (IS_ERR(gen->base[RSND_GEN1_SRU]) || 445 IS_ERR(gen->base[RSND_GEN1_ADG]) || 446 IS_ERR(gen->base[RSND_GEN1_SSI])) 447 return -ENODEV; 448 449 ret = rsnd_gen1_regmap_init(priv, gen); 450 if (ret < 0) 451 return ret; 452 453 dev_dbg(dev, "Gen1 device probed\n"); 454 dev_dbg(dev, "SRU : %pap => %p\n", &sru_res->start, 455 gen->base[RSND_GEN1_SRU]); 456 dev_dbg(dev, "ADG : %pap => %p\n", &adg_res->start, 457 gen->base[RSND_GEN1_ADG]); 458 dev_dbg(dev, "SSI : %pap => %p\n", &ssi_res->start, 459 gen->base[RSND_GEN1_SSI]); 460 461 return 0; 462 463 } 464 465 /* 466 * Gen 467 */ 468 static void rsnd_of_parse_gen(struct platform_device *pdev, 469 const struct rsnd_of_data *of_data, 470 struct rsnd_priv *priv) 471 { 472 struct rcar_snd_info *info = priv->info; 473 474 if (!of_data) 475 return; 476 477 info->flags = of_data->flags; 478 } 479 480 int rsnd_gen_probe(struct platform_device *pdev, 481 const struct rsnd_of_data *of_data, 482 struct rsnd_priv *priv) 483 { 484 struct device *dev = rsnd_priv_to_dev(priv); 485 struct rsnd_gen *gen; 486 int ret; 487 488 rsnd_of_parse_gen(pdev, of_data, priv); 489 490 gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); 491 if (!gen) { 492 dev_err(dev, "GEN allocate failed\n"); 493 return -ENOMEM; 494 } 495 496 priv->gen = gen; 497 498 ret = -ENODEV; 499 if (rsnd_is_gen1(priv)) 500 ret = rsnd_gen1_probe(pdev, priv); 501 else if (rsnd_is_gen2(priv)) 502 ret = rsnd_gen2_probe(pdev, priv); 503 504 if (ret < 0) 505 dev_err(dev, "unknown generation R-Car sound device\n"); 506 507 return ret; 508 } 509