linux/sound/soc/sh/rcar/gen.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Renesas R-Car Gen1 SRU/SSI support
   4//
   5// Copyright (C) 2013 Renesas Solutions Corp.
   6// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
   7
   8/*
   9 * #define DEBUG
  10 *
  11 * you can also add below in
  12 * ${LINUX}/drivers/base/regmap/regmap.c
  13 * for regmap debug
  14 *
  15 * #define LOG_DEVICE "xxxx.rcar_sound"
  16 */
  17
  18#include "rsnd.h"
  19
  20struct rsnd_gen {
  21        struct rsnd_gen_ops *ops;
  22
  23        /* RSND_BASE_MAX base */
  24        void __iomem *base[RSND_BASE_MAX];
  25        phys_addr_t res[RSND_BASE_MAX];
  26        struct regmap *regmap[RSND_BASE_MAX];
  27
  28        /* RSND_REG_MAX base */
  29        struct regmap_field *regs[RSND_REG_MAX];
  30        const char *reg_name[RSND_REG_MAX];
  31};
  32
  33#define rsnd_priv_to_gen(p)     ((struct rsnd_gen *)(p)->gen)
  34#define rsnd_reg_name(gen, id)  ((gen)->reg_name[id])
  35
  36struct rsnd_regmap_field_conf {
  37        int idx;
  38        unsigned int reg_offset;
  39        unsigned int id_offset;
  40        const char *reg_name;
  41};
  42
  43#define RSND_REG_SET(id, offset, _id_offset, n) \
  44{                                               \
  45        .idx = id,                              \
  46        .reg_offset = offset,                   \
  47        .id_offset = _id_offset,                \
  48        .reg_name = n,                          \
  49}
  50/* single address mapping */
  51#define RSND_GEN_S_REG(id, offset)      \
  52        RSND_REG_SET(RSND_REG_##id, offset, 0, #id)
  53
  54/* multi address mapping */
  55#define RSND_GEN_M_REG(id, offset, _id_offset)  \
  56        RSND_REG_SET(RSND_REG_##id, offset, _id_offset, #id)
  57
  58/*
  59 *              basic function
  60 */
  61static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
  62                                  struct rsnd_gen *gen, enum rsnd_reg reg)
  63{
  64        if (!gen->regs[reg]) {
  65                struct device *dev = rsnd_priv_to_dev(priv);
  66
  67                dev_err(dev, "unsupported register access %x\n", reg);
  68                return 0;
  69        }
  70
  71        return 1;
  72}
  73
  74u32 rsnd_read(struct rsnd_priv *priv,
  75              struct rsnd_mod *mod, enum rsnd_reg reg)
  76{
  77        struct device *dev = rsnd_priv_to_dev(priv);
  78        struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
  79        u32 val;
  80
  81        if (!rsnd_is_accessible_reg(priv, gen, reg))
  82                return 0;
  83
  84        regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);
  85
  86        dev_dbg(dev, "r %s[%d] - %-18s (%4d) : %08x\n",
  87                rsnd_mod_name(mod), rsnd_mod_id(mod),
  88                rsnd_reg_name(gen, reg), reg, val);
  89
  90        return val;
  91}
  92
  93void rsnd_write(struct rsnd_priv *priv,
  94                struct rsnd_mod *mod,
  95                enum rsnd_reg reg, u32 data)
  96{
  97        struct device *dev = rsnd_priv_to_dev(priv);
  98        struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
  99
 100        if (!rsnd_is_accessible_reg(priv, gen, reg))
 101                return;
 102
 103        regmap_fields_force_write(gen->regs[reg], rsnd_mod_id(mod), data);
 104
 105        dev_dbg(dev, "w %s[%d] - %-18s (%4d) : %08x\n",
 106                rsnd_mod_name(mod), rsnd_mod_id(mod),
 107                rsnd_reg_name(gen, reg), reg, data);
 108}
 109
 110void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
 111               enum rsnd_reg reg, u32 mask, u32 data)
 112{
 113        struct device *dev = rsnd_priv_to_dev(priv);
 114        struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
 115
 116        if (!rsnd_is_accessible_reg(priv, gen, reg))
 117                return;
 118
 119        regmap_fields_force_update_bits(gen->regs[reg],
 120                                        rsnd_mod_id(mod), mask, data);
 121
 122        dev_dbg(dev, "b %s[%d] - %-18s (%4d) : %08x/%08x\n",
 123                rsnd_mod_name(mod), rsnd_mod_id(mod),
 124                rsnd_reg_name(gen, reg), reg, data, mask);
 125
 126}
 127
 128phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id)
 129{
 130        struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
 131
 132        return  gen->res[reg_id];
 133}
 134
 135#define rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf)         \
 136        _rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf, ARRAY_SIZE(conf))
 137static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
 138                                 int id_size,
 139                                 int reg_id,
 140                                 const char *name,
 141                                 const struct rsnd_regmap_field_conf *conf,
 142                                 int conf_size)
 143{
 144        struct platform_device *pdev = rsnd_priv_to_pdev(priv);
 145        struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
 146        struct device *dev = rsnd_priv_to_dev(priv);
 147        struct resource *res;
 148        struct regmap_config regc;
 149        struct regmap_field *regs;
 150        struct regmap *regmap;
 151        struct reg_field regf;
 152        void __iomem *base;
 153        int i;
 154
 155        memset(&regc, 0, sizeof(regc));
 156        regc.reg_bits = 32;
 157        regc.val_bits = 32;
 158        regc.reg_stride = 4;
 159        regc.name = name;
 160
 161        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
 162        if (!res)
 163                res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id);
 164        if (!res)
 165                return -ENODEV;
 166
 167        base = devm_ioremap_resource(dev, res);
 168        if (IS_ERR(base))
 169                return PTR_ERR(base);
 170
 171        regmap = devm_regmap_init_mmio(dev, base, &regc);
 172        if (IS_ERR(regmap))
 173                return PTR_ERR(regmap);
 174
 175        /* RSND_BASE_MAX base */
 176        gen->base[reg_id] = base;
 177        gen->regmap[reg_id] = regmap;
 178        gen->res[reg_id] = res->start;
 179
 180        for (i = 0; i < conf_size; i++) {
 181
 182                regf.reg        = conf[i].reg_offset;
 183                regf.id_offset  = conf[i].id_offset;
 184                regf.lsb        = 0;
 185                regf.msb        = 31;
 186                regf.id_size    = id_size;
 187
 188                regs = devm_regmap_field_alloc(dev, regmap, regf);
 189                if (IS_ERR(regs))
 190                        return PTR_ERR(regs);
 191
 192                /* RSND_REG_MAX base */
 193                gen->regs[conf[i].idx] = regs;
 194                gen->reg_name[conf[i].idx] = conf[i].reg_name;
 195        }
 196
 197        return 0;
 198}
 199
 200/*
 201 *              Gen2
 202 */
 203static int rsnd_gen2_probe(struct rsnd_priv *priv)
 204{
 205        static const struct rsnd_regmap_field_conf conf_ssiu[] = {
 206                RSND_GEN_S_REG(SSI_MODE0,       0x800),
 207                RSND_GEN_S_REG(SSI_MODE1,       0x804),
 208                RSND_GEN_S_REG(SSI_MODE2,       0x808),
 209                RSND_GEN_S_REG(SSI_CONTROL,     0x810),
 210                RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840),
 211                RSND_GEN_S_REG(SSI_SYS_STATUS1, 0x844),
 212                RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848),
 213                RSND_GEN_S_REG(SSI_SYS_STATUS3, 0x84c),
 214                RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880),
 215                RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884),
 216                RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888),
 217                RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c),
 218                RSND_GEN_S_REG(HDMI0_SEL,       0x9e0),
 219                RSND_GEN_S_REG(HDMI1_SEL,       0x9e4),
 220
 221                /* FIXME: it needs SSI_MODE2/3 in the future */
 222                RSND_GEN_M_REG(SSI_BUSIF_MODE,  0x0,    0x80),
 223                RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4,    0x80),
 224                RSND_GEN_M_REG(SSI_BUSIF_DALIGN,0x8,    0x80),
 225                RSND_GEN_M_REG(SSI_MODE,        0xc,    0x80),
 226                RSND_GEN_M_REG(SSI_CTRL,        0x10,   0x80),
 227                RSND_GEN_M_REG(SSI_INT_ENABLE,  0x18,   0x80),
 228        };
 229
 230        static const struct rsnd_regmap_field_conf conf_scu[] = {
 231                RSND_GEN_M_REG(SRC_I_BUSIF_MODE,0x0,    0x20),
 232                RSND_GEN_M_REG(SRC_O_BUSIF_MODE,0x4,    0x20),
 233                RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8,    0x20),
 234                RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc,    0x20),
 235                RSND_GEN_M_REG(SRC_CTRL,        0x10,   0x20),
 236                RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18,   0x20),
 237                RSND_GEN_M_REG(CMD_BUSIF_MODE,  0x184,  0x20),
 238                RSND_GEN_M_REG(CMD_BUSIF_DALIGN,0x188,  0x20),
 239                RSND_GEN_M_REG(CMD_ROUTE_SLCT,  0x18c,  0x20),
 240                RSND_GEN_M_REG(CMD_CTRL,        0x190,  0x20),
 241                RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8),
 242                RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc),
 243                RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0),
 244                RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1d4),
 245                RSND_GEN_M_REG(SRC_SWRSR,       0x200,  0x40),
 246                RSND_GEN_M_REG(SRC_SRCIR,       0x204,  0x40),
 247                RSND_GEN_M_REG(SRC_ADINR,       0x214,  0x40),
 248                RSND_GEN_M_REG(SRC_IFSCR,       0x21c,  0x40),
 249                RSND_GEN_M_REG(SRC_IFSVR,       0x220,  0x40),
 250                RSND_GEN_M_REG(SRC_SRCCR,       0x224,  0x40),
 251                RSND_GEN_M_REG(SRC_BSDSR,       0x22c,  0x40),
 252                RSND_GEN_M_REG(SRC_BSISR,       0x238,  0x40),
 253                RSND_GEN_M_REG(CTU_SWRSR,       0x500,  0x100),
 254                RSND_GEN_M_REG(CTU_CTUIR,       0x504,  0x100),
 255                RSND_GEN_M_REG(CTU_ADINR,       0x508,  0x100),
 256                RSND_GEN_M_REG(CTU_CPMDR,       0x510,  0x100),
 257                RSND_GEN_M_REG(CTU_SCMDR,       0x514,  0x100),
 258                RSND_GEN_M_REG(CTU_SV00R,       0x518,  0x100),
 259                RSND_GEN_M_REG(CTU_SV01R,       0x51c,  0x100),
 260                RSND_GEN_M_REG(CTU_SV02R,       0x520,  0x100),
 261                RSND_GEN_M_REG(CTU_SV03R,       0x524,  0x100),
 262                RSND_GEN_M_REG(CTU_SV04R,       0x528,  0x100),
 263                RSND_GEN_M_REG(CTU_SV05R,       0x52c,  0x100),
 264                RSND_GEN_M_REG(CTU_SV06R,       0x530,  0x100),
 265                RSND_GEN_M_REG(CTU_SV07R,       0x534,  0x100),
 266                RSND_GEN_M_REG(CTU_SV10R,       0x538,  0x100),
 267                RSND_GEN_M_REG(CTU_SV11R,       0x53c,  0x100),
 268                RSND_GEN_M_REG(CTU_SV12R,       0x540,  0x100),
 269                RSND_GEN_M_REG(CTU_SV13R,       0x544,  0x100),
 270                RSND_GEN_M_REG(CTU_SV14R,       0x548,  0x100),
 271                RSND_GEN_M_REG(CTU_SV15R,       0x54c,  0x100),
 272                RSND_GEN_M_REG(CTU_SV16R,       0x550,  0x100),
 273                RSND_GEN_M_REG(CTU_SV17R,       0x554,  0x100),
 274                RSND_GEN_M_REG(CTU_SV20R,       0x558,  0x100),
 275                RSND_GEN_M_REG(CTU_SV21R,       0x55c,  0x100),
 276                RSND_GEN_M_REG(CTU_SV22R,       0x560,  0x100),
 277                RSND_GEN_M_REG(CTU_SV23R,       0x564,  0x100),
 278                RSND_GEN_M_REG(CTU_SV24R,       0x568,  0x100),
 279                RSND_GEN_M_REG(CTU_SV25R,       0x56c,  0x100),
 280                RSND_GEN_M_REG(CTU_SV26R,       0x570,  0x100),
 281                RSND_GEN_M_REG(CTU_SV27R,       0x574,  0x100),
 282                RSND_GEN_M_REG(CTU_SV30R,       0x578,  0x100),
 283                RSND_GEN_M_REG(CTU_SV31R,       0x57c,  0x100),
 284                RSND_GEN_M_REG(CTU_SV32R,       0x580,  0x100),
 285                RSND_GEN_M_REG(CTU_SV33R,       0x584,  0x100),
 286                RSND_GEN_M_REG(CTU_SV34R,       0x588,  0x100),
 287                RSND_GEN_M_REG(CTU_SV35R,       0x58c,  0x100),
 288                RSND_GEN_M_REG(CTU_SV36R,       0x590,  0x100),
 289                RSND_GEN_M_REG(CTU_SV37R,       0x594,  0x100),
 290                RSND_GEN_M_REG(MIX_SWRSR,       0xd00,  0x40),
 291                RSND_GEN_M_REG(MIX_MIXIR,       0xd04,  0x40),
 292                RSND_GEN_M_REG(MIX_ADINR,       0xd08,  0x40),
 293                RSND_GEN_M_REG(MIX_MIXMR,       0xd10,  0x40),
 294                RSND_GEN_M_REG(MIX_MVPDR,       0xd14,  0x40),
 295                RSND_GEN_M_REG(MIX_MDBAR,       0xd18,  0x40),
 296                RSND_GEN_M_REG(MIX_MDBBR,       0xd1c,  0x40),
 297                RSND_GEN_M_REG(MIX_MDBCR,       0xd20,  0x40),
 298                RSND_GEN_M_REG(MIX_MDBDR,       0xd24,  0x40),
 299                RSND_GEN_M_REG(MIX_MDBER,       0xd28,  0x40),
 300                RSND_GEN_M_REG(DVC_SWRSR,       0xe00,  0x100),
 301                RSND_GEN_M_REG(DVC_DVUIR,       0xe04,  0x100),
 302                RSND_GEN_M_REG(DVC_ADINR,       0xe08,  0x100),
 303                RSND_GEN_M_REG(DVC_DVUCR,       0xe10,  0x100),
 304                RSND_GEN_M_REG(DVC_ZCMCR,       0xe14,  0x100),
 305                RSND_GEN_M_REG(DVC_VRCTR,       0xe18,  0x100),
 306                RSND_GEN_M_REG(DVC_VRPDR,       0xe1c,  0x100),
 307                RSND_GEN_M_REG(DVC_VRDBR,       0xe20,  0x100),
 308                RSND_GEN_M_REG(DVC_VOL0R,       0xe28,  0x100),
 309                RSND_GEN_M_REG(DVC_VOL1R,       0xe2c,  0x100),
 310                RSND_GEN_M_REG(DVC_VOL2R,       0xe30,  0x100),
 311                RSND_GEN_M_REG(DVC_VOL3R,       0xe34,  0x100),
 312                RSND_GEN_M_REG(DVC_VOL4R,       0xe38,  0x100),
 313                RSND_GEN_M_REG(DVC_VOL5R,       0xe3c,  0x100),
 314                RSND_GEN_M_REG(DVC_VOL6R,       0xe40,  0x100),
 315                RSND_GEN_M_REG(DVC_VOL7R,       0xe44,  0x100),
 316                RSND_GEN_M_REG(DVC_DVUER,       0xe48,  0x100),
 317        };
 318        static const struct rsnd_regmap_field_conf conf_adg[] = {
 319                RSND_GEN_S_REG(BRRA,            0x00),
 320                RSND_GEN_S_REG(BRRB,            0x04),
 321                RSND_GEN_S_REG(BRGCKR,          0x08),
 322                RSND_GEN_S_REG(AUDIO_CLK_SEL0,  0x0c),
 323                RSND_GEN_S_REG(AUDIO_CLK_SEL1,  0x10),
 324                RSND_GEN_S_REG(AUDIO_CLK_SEL2,  0x14),
 325                RSND_GEN_S_REG(DIV_EN,          0x30),
 326                RSND_GEN_S_REG(SRCIN_TIMSEL0,   0x34),
 327                RSND_GEN_S_REG(SRCIN_TIMSEL1,   0x38),
 328                RSND_GEN_S_REG(SRCIN_TIMSEL2,   0x3c),
 329                RSND_GEN_S_REG(SRCIN_TIMSEL3,   0x40),
 330                RSND_GEN_S_REG(SRCIN_TIMSEL4,   0x44),
 331                RSND_GEN_S_REG(SRCOUT_TIMSEL0,  0x48),
 332                RSND_GEN_S_REG(SRCOUT_TIMSEL1,  0x4c),
 333                RSND_GEN_S_REG(SRCOUT_TIMSEL2,  0x50),
 334                RSND_GEN_S_REG(SRCOUT_TIMSEL3,  0x54),
 335                RSND_GEN_S_REG(SRCOUT_TIMSEL4,  0x58),
 336                RSND_GEN_S_REG(CMDOUT_TIMSEL,   0x5c),
 337        };
 338        static const struct rsnd_regmap_field_conf conf_ssi[] = {
 339                RSND_GEN_M_REG(SSICR,           0x00,   0x40),
 340                RSND_GEN_M_REG(SSISR,           0x04,   0x40),
 341                RSND_GEN_M_REG(SSITDR,          0x08,   0x40),
 342                RSND_GEN_M_REG(SSIRDR,          0x0c,   0x40),
 343                RSND_GEN_M_REG(SSIWSR,          0x20,   0x40),
 344        };
 345        int ret_ssiu;
 346        int ret_scu;
 347        int ret_adg;
 348        int ret_ssi;
 349
 350        ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, "ssiu", conf_ssiu);
 351        ret_scu  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU,  "scu",  conf_scu);
 352        ret_adg  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG,  "adg",  conf_adg);
 353        ret_ssi  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI,  "ssi",  conf_ssi);
 354        if (ret_ssiu < 0 ||
 355            ret_scu  < 0 ||
 356            ret_adg  < 0 ||
 357            ret_ssi  < 0)
 358                return ret_ssiu | ret_scu | ret_adg | ret_ssi;
 359
 360        return 0;
 361}
 362
 363/*
 364 *              Gen1
 365 */
 366
 367static int rsnd_gen1_probe(struct rsnd_priv *priv)
 368{
 369        static const struct rsnd_regmap_field_conf conf_adg[] = {
 370                RSND_GEN_S_REG(BRRA,            0x00),
 371                RSND_GEN_S_REG(BRRB,            0x04),
 372                RSND_GEN_S_REG(BRGCKR,          0x08),
 373                RSND_GEN_S_REG(AUDIO_CLK_SEL0,  0x0c),
 374                RSND_GEN_S_REG(AUDIO_CLK_SEL1,  0x10),
 375        };
 376        static const struct rsnd_regmap_field_conf conf_ssi[] = {
 377                RSND_GEN_M_REG(SSICR,           0x00,   0x40),
 378                RSND_GEN_M_REG(SSISR,           0x04,   0x40),
 379                RSND_GEN_M_REG(SSITDR,          0x08,   0x40),
 380                RSND_GEN_M_REG(SSIRDR,          0x0c,   0x40),
 381                RSND_GEN_M_REG(SSIWSR,          0x20,   0x40),
 382        };
 383        int ret_adg;
 384        int ret_ssi;
 385
 386        ret_adg  = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, "adg", conf_adg);
 387        ret_ssi  = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, "ssi", conf_ssi);
 388        if (ret_adg  < 0 ||
 389            ret_ssi  < 0)
 390                return ret_adg | ret_ssi;
 391
 392        return 0;
 393}
 394
 395/*
 396 *              Gen
 397 */
 398int rsnd_gen_probe(struct rsnd_priv *priv)
 399{
 400        struct device *dev = rsnd_priv_to_dev(priv);
 401        struct rsnd_gen *gen;
 402        int ret;
 403
 404        gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
 405        if (!gen)
 406                return -ENOMEM;
 407
 408        priv->gen = gen;
 409
 410        ret = -ENODEV;
 411        if (rsnd_is_gen1(priv))
 412                ret = rsnd_gen1_probe(priv);
 413        else if (rsnd_is_gen2(priv) ||
 414                 rsnd_is_gen3(priv))
 415                ret = rsnd_gen2_probe(priv);
 416
 417        if (ret < 0)
 418                dev_err(dev, "unknown generation R-Car sound device\n");
 419
 420        return ret;
 421}
 422