Merge remote-tracking branches 'asoc/topic/rcar', 'asoc/topic/reg-default', 'asoc/topic/rl6231', 'asoc/topic/rockchip' and 'asoc/topic/rt286' into asoc-next

This commit is contained in:
Mark Brown 2015-08-30 15:55:54 +01:00
46 changed files with 1142 additions and 304 deletions

View File

@ -18,6 +18,12 @@ Required properties:
- rcar_sound,src : Should contain SRC feature. - rcar_sound,src : Should contain SRC feature.
The number of SRC subnode should be same as HW. The number of SRC subnode should be same as HW.
see below for detail. see below for detail.
- rcar_sound,ctu : Should contain CTU feature.
The number of CTU subnode should be same as HW.
see below for detail.
- rcar_sound,mix : Should contain MIX feature.
The number of MIX subnode should be same as HW.
see below for detail.
- rcar_sound,dvc : Should contain DVC feature. - rcar_sound,dvc : Should contain DVC feature.
The number of DVC subnode should be same as HW. The number of DVC subnode should be same as HW.
see below for detail. see below for detail.
@ -90,6 +96,22 @@ rcar_sound: sound@ec500000 {
}; };
}; };
rcar_sound,mix {
mix0: mix@0 { };
mix1: mix@1 { };
};
rcar_sound,ctu {
ctu00: ctu@0 { };
ctu01: ctu@1 { };
ctu02: ctu@2 { };
ctu03: ctu@3 { };
ctu10: ctu@4 { };
ctu11: ctu@5 { };
ctu12: ctu@6 { };
ctu13: ctu@7 { };
};
rcar_sound,src { rcar_sound,src {
src0: src@0 { src0: src@0 {
interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>;

View File

@ -6,6 +6,7 @@ Required properties:
- compatible : "renesas,rsrc-card,<board>" - compatible : "renesas,rsrc-card,<board>"
Examples with soctypes are: Examples with soctypes are:
- "renesas,rsrc-card"
- "renesas,rsrc-card,lager" - "renesas,rsrc-card,lager"
- "renesas,rsrc-card,koelsch" - "renesas,rsrc-card,koelsch"
Optional properties: Optional properties:
@ -29,6 +30,12 @@ Optional subnode properties:
- frame-inversion : bool property. Add this if the - frame-inversion : bool property. Add this if the
dai-link uses frame clock inversion. dai-link uses frame clock inversion.
- convert-rate : platform specified sampling rate convert - convert-rate : platform specified sampling rate convert
- audio-prefix : see audio-routing
- audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources.
use audio-prefix if some components is using same sink/sources naming.
it can be used if compatible was "renesas,rsrc-card";
Required CPU/CODEC subnodes properties: Required CPU/CODEC subnodes properties:

View File

@ -136,7 +136,7 @@ struct regmap {
/* if set, the HW registers are known to match map->reg_defaults */ /* if set, the HW registers are known to match map->reg_defaults */
bool no_sync_defaults; bool no_sync_defaults;
struct reg_default *patch; struct reg_sequence *patch;
int patch_regs; int patch_regs;
/* if set, converts bulk rw to single rw */ /* if set, converts bulk rw to single rw */

View File

@ -34,7 +34,7 @@
static int _regmap_update_bits(struct regmap *map, unsigned int reg, static int _regmap_update_bits(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val, unsigned int mask, unsigned int val,
bool *change); bool *change, bool force_write);
static int _regmap_bus_reg_read(void *context, unsigned int reg, static int _regmap_bus_reg_read(void *context, unsigned int reg,
unsigned int *val); unsigned int *val);
@ -1178,7 +1178,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
ret = _regmap_update_bits(map, range->selector_reg, ret = _regmap_update_bits(map, range->selector_reg,
range->selector_mask, range->selector_mask,
win_page << range->selector_shift, win_page << range->selector_shift,
&page_chg); &page_chg, false);
map->work_buf = orig_work_buf; map->work_buf = orig_work_buf;
@ -1624,6 +1624,18 @@ int regmap_fields_write(struct regmap_field *field, unsigned int id,
} }
EXPORT_SYMBOL_GPL(regmap_fields_write); EXPORT_SYMBOL_GPL(regmap_fields_write);
int regmap_fields_force_write(struct regmap_field *field, unsigned int id,
unsigned int val)
{
if (id >= field->id_size)
return -EINVAL;
return regmap_write_bits(field->regmap,
field->reg + (field->id_offset * id),
field->mask, val << field->shift);
}
EXPORT_SYMBOL_GPL(regmap_fields_force_write);
/** /**
* regmap_fields_update_bits(): Perform a read/modify/write cycle * regmap_fields_update_bits(): Perform a read/modify/write cycle
* on the register field * on the register field
@ -1743,7 +1755,7 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write);
* relative. The page register has been written if that was neccessary. * relative. The page register has been written if that was neccessary.
*/ */
static int _regmap_raw_multi_reg_write(struct regmap *map, static int _regmap_raw_multi_reg_write(struct regmap *map,
const struct reg_default *regs, const struct reg_sequence *regs,
size_t num_regs) size_t num_regs)
{ {
int ret; int ret;
@ -1800,12 +1812,12 @@ static unsigned int _regmap_register_page(struct regmap *map,
} }
static int _regmap_range_multi_paged_reg_write(struct regmap *map, static int _regmap_range_multi_paged_reg_write(struct regmap *map,
struct reg_default *regs, struct reg_sequence *regs,
size_t num_regs) size_t num_regs)
{ {
int ret; int ret;
int i, n; int i, n;
struct reg_default *base; struct reg_sequence *base;
unsigned int this_page = 0; unsigned int this_page = 0;
/* /*
* the set of registers are not neccessarily in order, but * the set of registers are not neccessarily in order, but
@ -1843,7 +1855,7 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map,
} }
static int _regmap_multi_reg_write(struct regmap *map, static int _regmap_multi_reg_write(struct regmap *map,
const struct reg_default *regs, const struct reg_sequence *regs,
size_t num_regs) size_t num_regs)
{ {
int i; int i;
@ -1895,8 +1907,8 @@ static int _regmap_multi_reg_write(struct regmap *map,
struct regmap_range_node *range; struct regmap_range_node *range;
range = _regmap_range_lookup(map, reg); range = _regmap_range_lookup(map, reg);
if (range) { if (range) {
size_t len = sizeof(struct reg_default)*num_regs; size_t len = sizeof(struct reg_sequence)*num_regs;
struct reg_default *base = kmemdup(regs, len, struct reg_sequence *base = kmemdup(regs, len,
GFP_KERNEL); GFP_KERNEL);
if (!base) if (!base)
return -ENOMEM; return -ENOMEM;
@ -1929,7 +1941,7 @@ static int _regmap_multi_reg_write(struct regmap *map,
* A value of zero will be returned on success, a negative errno will be * A value of zero will be returned on success, a negative errno will be
* returned in error cases. * returned in error cases.
*/ */
int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs,
int num_regs) int num_regs)
{ {
int ret; int ret;
@ -1962,7 +1974,7 @@ EXPORT_SYMBOL_GPL(regmap_multi_reg_write);
* be returned in error cases. * be returned in error cases.
*/ */
int regmap_multi_reg_write_bypassed(struct regmap *map, int regmap_multi_reg_write_bypassed(struct regmap *map,
const struct reg_default *regs, const struct reg_sequence *regs,
int num_regs) int num_regs)
{ {
int ret; int ret;
@ -2327,7 +2339,7 @@ EXPORT_SYMBOL_GPL(regmap_bulk_read);
static int _regmap_update_bits(struct regmap *map, unsigned int reg, static int _regmap_update_bits(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val, unsigned int mask, unsigned int val,
bool *change) bool *change, bool force_write)
{ {
int ret; int ret;
unsigned int tmp, orig; unsigned int tmp, orig;
@ -2339,7 +2351,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
tmp = orig & ~mask; tmp = orig & ~mask;
tmp |= val & mask; tmp |= val & mask;
if (tmp != orig) { if (force_write || (tmp != orig)) {
ret = _regmap_write(map, reg, tmp); ret = _regmap_write(map, reg, tmp);
if (change) if (change)
*change = true; *change = true;
@ -2367,13 +2379,36 @@ int regmap_update_bits(struct regmap *map, unsigned int reg,
int ret; int ret;
map->lock(map->lock_arg); map->lock(map->lock_arg);
ret = _regmap_update_bits(map, reg, mask, val, NULL); ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
map->unlock(map->lock_arg); map->unlock(map->lock_arg);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(regmap_update_bits); EXPORT_SYMBOL_GPL(regmap_update_bits);
/**
* regmap_write_bits: Perform a read/modify/write cycle on the register map
*
* @map: Register map to update
* @reg: Register to update
* @mask: Bitmask to change
* @val: New value for bitmask
*
* Returns zero for success, a negative number on error.
*/
int regmap_write_bits(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val)
{
int ret;
map->lock(map->lock_arg);
ret = _regmap_update_bits(map, reg, mask, val, NULL, true);
map->unlock(map->lock_arg);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_write_bits);
/** /**
* regmap_update_bits_async: Perform a read/modify/write cycle on the register * regmap_update_bits_async: Perform a read/modify/write cycle on the register
* map asynchronously * map asynchronously
@ -2398,7 +2433,7 @@ int regmap_update_bits_async(struct regmap *map, unsigned int reg,
map->async = true; map->async = true;
ret = _regmap_update_bits(map, reg, mask, val, NULL); ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
map->async = false; map->async = false;
@ -2427,7 +2462,7 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
int ret; int ret;
map->lock(map->lock_arg); map->lock(map->lock_arg);
ret = _regmap_update_bits(map, reg, mask, val, change); ret = _regmap_update_bits(map, reg, mask, val, change, false);
map->unlock(map->lock_arg); map->unlock(map->lock_arg);
return ret; return ret;
} }
@ -2460,7 +2495,7 @@ int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
map->async = true; map->async = true;
ret = _regmap_update_bits(map, reg, mask, val, change); ret = _regmap_update_bits(map, reg, mask, val, change, false);
map->async = false; map->async = false;
@ -2552,10 +2587,10 @@ EXPORT_SYMBOL_GPL(regmap_async_complete);
* The caller must ensure that this function cannot be called * The caller must ensure that this function cannot be called
* concurrently with either itself or regcache_sync(). * concurrently with either itself or regcache_sync().
*/ */
int regmap_register_patch(struct regmap *map, const struct reg_default *regs, int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs,
int num_regs) int num_regs)
{ {
struct reg_default *p; struct reg_sequence *p;
int ret; int ret;
bool bypass; bool bypass;
@ -2564,7 +2599,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
return 0; return 0;
p = krealloc(map->patch, p = krealloc(map->patch,
sizeof(struct reg_default) * (map->patch_regs + num_regs), sizeof(struct reg_sequence) * (map->patch_regs + num_regs),
GFP_KERNEL); GFP_KERNEL);
if (p) { if (p) {
memcpy(p + map->patch_regs, regs, num_regs * sizeof(*regs)); memcpy(p + map->patch_regs, regs, num_regs * sizeof(*regs));

View File

@ -54,7 +54,7 @@ static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder)
} }
/* ADI recommended values for proper operation. */ /* ADI recommended values for proper operation. */
static const struct reg_default adv7511_fixed_registers[] = { static const struct reg_sequence adv7511_fixed_registers[] = {
{ 0x98, 0x03 }, { 0x98, 0x03 },
{ 0x9a, 0xe0 }, { 0x9a, 0xe0 },
{ 0x9c, 0x30 }, { 0x9c, 0x30 },

View File

@ -313,14 +313,14 @@ static void drv260x_close(struct input_dev *input)
gpiod_set_value(haptics->enable_gpio, 0); gpiod_set_value(haptics->enable_gpio, 0);
} }
static const struct reg_default drv260x_lra_cal_regs[] = { static const struct reg_sequence drv260x_lra_cal_regs[] = {
{ DRV260X_MODE, DRV260X_AUTO_CAL }, { DRV260X_MODE, DRV260X_AUTO_CAL },
{ DRV260X_CTRL3, DRV260X_NG_THRESH_2 }, { DRV260X_CTRL3, DRV260X_NG_THRESH_2 },
{ DRV260X_FEEDBACK_CTRL, DRV260X_FB_REG_LRA_MODE | { DRV260X_FEEDBACK_CTRL, DRV260X_FB_REG_LRA_MODE |
DRV260X_BRAKE_FACTOR_4X | DRV260X_LOOP_GAIN_HIGH }, DRV260X_BRAKE_FACTOR_4X | DRV260X_LOOP_GAIN_HIGH },
}; };
static const struct reg_default drv260x_lra_init_regs[] = { static const struct reg_sequence drv260x_lra_init_regs[] = {
{ DRV260X_MODE, DRV260X_RT_PLAYBACK }, { DRV260X_MODE, DRV260X_RT_PLAYBACK },
{ DRV260X_A_TO_V_CTRL, DRV260X_AUDIO_HAPTICS_PEAK_20MS | { DRV260X_A_TO_V_CTRL, DRV260X_AUDIO_HAPTICS_PEAK_20MS |
DRV260X_AUDIO_HAPTICS_FILTER_125HZ }, DRV260X_AUDIO_HAPTICS_FILTER_125HZ },
@ -337,7 +337,7 @@ static const struct reg_default drv260x_lra_init_regs[] = {
{ DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS }, { DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS },
}; };
static const struct reg_default drv260x_erm_cal_regs[] = { static const struct reg_sequence drv260x_erm_cal_regs[] = {
{ DRV260X_MODE, DRV260X_AUTO_CAL }, { DRV260X_MODE, DRV260X_AUTO_CAL },
{ DRV260X_A_TO_V_MIN_INPUT, DRV260X_AUDIO_HAPTICS_MIN_IN_VOLT }, { DRV260X_A_TO_V_MIN_INPUT, DRV260X_AUDIO_HAPTICS_MIN_IN_VOLT },
{ DRV260X_A_TO_V_MAX_INPUT, DRV260X_AUDIO_HAPTICS_MAX_IN_VOLT }, { DRV260X_A_TO_V_MAX_INPUT, DRV260X_AUDIO_HAPTICS_MAX_IN_VOLT },

View File

@ -132,7 +132,7 @@ static void drv2665_close(struct input_dev *input)
"Failed to enter standby mode: %d\n", error); "Failed to enter standby mode: %d\n", error);
} }
static const struct reg_default drv2665_init_regs[] = { static const struct reg_sequence drv2665_init_regs[] = {
{ DRV2665_CTRL_2, 0 | DRV2665_10_MS_IDLE_TOUT }, { DRV2665_CTRL_2, 0 | DRV2665_10_MS_IDLE_TOUT },
{ DRV2665_CTRL_1, DRV2665_25_VPP_GAIN }, { DRV2665_CTRL_1, DRV2665_25_VPP_GAIN },
}; };

View File

@ -262,14 +262,14 @@ static void drv2667_close(struct input_dev *input)
"Failed to enter standby mode: %d\n", error); "Failed to enter standby mode: %d\n", error);
} }
static const struct reg_default drv2667_init_regs[] = { static const struct reg_sequence drv2667_init_regs[] = {
{ DRV2667_CTRL_2, 0 }, { DRV2667_CTRL_2, 0 },
{ DRV2667_CTRL_1, DRV2667_25_VPP_GAIN }, { DRV2667_CTRL_1, DRV2667_25_VPP_GAIN },
{ DRV2667_WV_SEQ_0, 1 }, { DRV2667_WV_SEQ_0, 1 },
{ DRV2667_WV_SEQ_1, 0 } { DRV2667_WV_SEQ_1, 0 }
}; };
static const struct reg_default drv2667_page1_init[] = { static const struct reg_sequence drv2667_page1_init[] = {
{ DRV2667_RAM_HDR_SZ, 0x05 }, { DRV2667_RAM_HDR_SZ, 0x05 },
{ DRV2667_RAM_START_HI, 0x80 }, { DRV2667_RAM_START_HI, 0x80 },
{ DRV2667_RAM_START_LO, 0x06 }, { DRV2667_RAM_START_LO, 0x06 },

View File

@ -392,7 +392,7 @@ err:
* Register patch to some of the CODECs internal write sequences * Register patch to some of the CODECs internal write sequences
* to ensure a clean exit from the low power sleep state. * to ensure a clean exit from the low power sleep state.
*/ */
static const struct reg_default wm5110_sleep_patch[] = { static const struct reg_sequence wm5110_sleep_patch[] = {
{ 0x337A, 0xC100 }, { 0x337A, 0xC100 },
{ 0x337B, 0x0041 }, { 0x337B, 0x0041 },
{ 0x3300, 0xA210 }, { 0x3300, 0xA210 },

View File

@ -86,7 +86,7 @@ static const struct reg_default twl6040_defaults[] = {
{ 0x2E, 0x00 }, /* REG_STATUS (ro) */ { 0x2E, 0x00 }, /* REG_STATUS (ro) */
}; };
static struct reg_default twl6040_patch[] = { static struct reg_sequence twl6040_patch[] = {
/* /*
* Select I2C bus access to dual access registers * Select I2C bus access to dual access registers
* Interrupt register is cleared on read * Interrupt register is cleared on read

View File

@ -21,7 +21,7 @@
#define WM5102_NUM_AOD_ISR 2 #define WM5102_NUM_AOD_ISR 2
#define WM5102_NUM_ISR 5 #define WM5102_NUM_ISR 5
static const struct reg_default wm5102_reva_patch[] = { static const struct reg_sequence wm5102_reva_patch[] = {
{ 0x80, 0x0003 }, { 0x80, 0x0003 },
{ 0x221, 0x0090 }, { 0x221, 0x0090 },
{ 0x211, 0x0014 }, { 0x211, 0x0014 },
@ -57,7 +57,7 @@ static const struct reg_default wm5102_reva_patch[] = {
{ 0x80, 0x0000 }, { 0x80, 0x0000 },
}; };
static const struct reg_default wm5102_revb_patch[] = { static const struct reg_sequence wm5102_revb_patch[] = {
{ 0x19, 0x0001 }, { 0x19, 0x0001 },
{ 0x80, 0x0003 }, { 0x80, 0x0003 },
{ 0x081, 0xE022 }, { 0x081, 0xE022 },
@ -80,7 +80,7 @@ static const struct reg_default wm5102_revb_patch[] = {
/* We use a function so we can use ARRAY_SIZE() */ /* We use a function so we can use ARRAY_SIZE() */
int wm5102_patch(struct arizona *arizona) int wm5102_patch(struct arizona *arizona)
{ {
const struct reg_default *wm5102_patch; const struct reg_sequence *wm5102_patch;
int patch_size; int patch_size;
switch (arizona->rev) { switch (arizona->rev) {

View File

@ -21,7 +21,7 @@
#define WM5110_NUM_AOD_ISR 2 #define WM5110_NUM_AOD_ISR 2
#define WM5110_NUM_ISR 5 #define WM5110_NUM_ISR 5
static const struct reg_default wm5110_reva_patch[] = { static const struct reg_sequence wm5110_reva_patch[] = {
{ 0x80, 0x3 }, { 0x80, 0x3 },
{ 0x44, 0x20 }, { 0x44, 0x20 },
{ 0x45, 0x40 }, { 0x45, 0x40 },
@ -134,7 +134,7 @@ static const struct reg_default wm5110_reva_patch[] = {
{ 0x209, 0x002A }, { 0x209, 0x002A },
}; };
static const struct reg_default wm5110_revb_patch[] = { static const struct reg_sequence wm5110_revb_patch[] = {
{ 0x80, 0x3 }, { 0x80, 0x3 },
{ 0x36e, 0x0210 }, { 0x36e, 0x0210 },
{ 0x370, 0x0210 }, { 0x370, 0x0210 },
@ -224,7 +224,7 @@ static const struct reg_default wm5110_revb_patch[] = {
{ 0x80, 0x0 }, { 0x80, 0x0 },
}; };
static const struct reg_default wm5110_revd_patch[] = { static const struct reg_sequence wm5110_revd_patch[] = {
{ 0x80, 0x3 }, { 0x80, 0x3 },
{ 0x80, 0x3 }, { 0x80, 0x3 },
{ 0x393, 0x27 }, { 0x393, 0x27 },

View File

@ -243,21 +243,21 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
} }
#endif #endif
static const struct reg_default wm8994_revc_patch[] = { static const struct reg_sequence wm8994_revc_patch[] = {
{ 0x102, 0x3 }, { 0x102, 0x3 },
{ 0x56, 0x3 }, { 0x56, 0x3 },
{ 0x817, 0x0 }, { 0x817, 0x0 },
{ 0x102, 0x0 }, { 0x102, 0x0 },
}; };
static const struct reg_default wm8958_reva_patch[] = { static const struct reg_sequence wm8958_reva_patch[] = {
{ 0x102, 0x3 }, { 0x102, 0x3 },
{ 0xcb, 0x81 }, { 0xcb, 0x81 },
{ 0x817, 0x0 }, { 0x817, 0x0 },
{ 0x102, 0x0 }, { 0x102, 0x0 },
}; };
static const struct reg_default wm1811_reva_patch[] = { static const struct reg_sequence wm1811_reva_patch[] = {
{ 0x102, 0x3 }, { 0x102, 0x3 },
{ 0x56, 0xc07 }, { 0x56, 0xc07 },
{ 0x5d, 0x7e }, { 0x5d, 0x7e },
@ -326,7 +326,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
{ {
struct wm8994_pdata *pdata; struct wm8994_pdata *pdata;
struct regmap_config *regmap_config; struct regmap_config *regmap_config;
const struct reg_default *regmap_patch = NULL; const struct reg_sequence *regmap_patch = NULL;
const char *devname; const char *devname;
int ret, i, patch_regs = 0; int ret, i, patch_regs = 0;
int pulls = 0; int pulls = 0;

View File

@ -17,7 +17,7 @@
#include "arizona.h" #include "arizona.h"
static const struct reg_default wm8997_reva_patch[] = { static const struct reg_sequence wm8997_reva_patch[] = {
{ 0x80, 0x0003 }, { 0x80, 0x0003 },
{ 0x214, 0x0008 }, { 0x214, 0x0008 },
{ 0x458, 0x0000 }, { 0x458, 0x0000 },

View File

@ -50,6 +50,17 @@ struct reg_default {
unsigned int def; unsigned int def;
}; };
/**
* Register/value pairs for sequences of writes
*
* @reg: Register address.
* @def: Register value.
*/
struct reg_sequence {
unsigned int reg;
unsigned int def;
};
#ifdef CONFIG_REGMAP #ifdef CONFIG_REGMAP
enum regmap_endian { enum regmap_endian {
@ -410,10 +421,10 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
const void *val, size_t val_len); const void *val, size_t val_len);
int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
size_t val_count); size_t val_count);
int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs,
int num_regs); int num_regs);
int regmap_multi_reg_write_bypassed(struct regmap *map, int regmap_multi_reg_write_bypassed(struct regmap *map,
const struct reg_default *regs, const struct reg_sequence *regs,
int num_regs); int num_regs);
int regmap_raw_write_async(struct regmap *map, unsigned int reg, int regmap_raw_write_async(struct regmap *map, unsigned int reg,
const void *val, size_t val_len); const void *val, size_t val_len);
@ -424,6 +435,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
size_t val_count); size_t val_count);
int regmap_update_bits(struct regmap *map, unsigned int reg, int regmap_update_bits(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val); unsigned int mask, unsigned int val);
int regmap_write_bits(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val);
int regmap_update_bits_async(struct regmap *map, unsigned int reg, int regmap_update_bits_async(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val); unsigned int mask, unsigned int val);
int regmap_update_bits_check(struct regmap *map, unsigned int reg, int regmap_update_bits_check(struct regmap *map, unsigned int reg,
@ -450,7 +463,7 @@ void regcache_mark_dirty(struct regmap *map);
bool regmap_check_range_table(struct regmap *map, unsigned int reg, bool regmap_check_range_table(struct regmap *map, unsigned int reg,
const struct regmap_access_table *table); const struct regmap_access_table *table);
int regmap_register_patch(struct regmap *map, const struct reg_default *regs, int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs,
int num_regs); int num_regs);
int regmap_parse_val(struct regmap *map, const void *buf, int regmap_parse_val(struct regmap *map, const void *buf,
unsigned int *val); unsigned int *val);
@ -503,6 +516,8 @@ int regmap_field_update_bits(struct regmap_field *field,
int regmap_fields_write(struct regmap_field *field, unsigned int id, int regmap_fields_write(struct regmap_field *field, unsigned int id,
unsigned int val); unsigned int val);
int regmap_fields_force_write(struct regmap_field *field, unsigned int id,
unsigned int val);
int regmap_fields_read(struct regmap_field *field, unsigned int id, int regmap_fields_read(struct regmap_field *field, unsigned int id,
unsigned int *val); unsigned int *val);
int regmap_fields_update_bits(struct regmap_field *field, unsigned int id, int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
@ -645,6 +660,13 @@ static inline int regmap_update_bits(struct regmap *map, unsigned int reg,
return -EINVAL; return -EINVAL;
} }
static inline int regmap_write_bits(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val)
{
WARN_ONCE(1, "regmap API is disabled");
return -EINVAL;
}
static inline int regmap_update_bits_async(struct regmap *map, static inline int regmap_update_bits_async(struct regmap *map,
unsigned int reg, unsigned int reg,
unsigned int mask, unsigned int val) unsigned int mask, unsigned int val)

View File

@ -61,6 +61,14 @@ struct rsnd_src_platform_info {
/* /*
* flags * flags
*/ */
struct rsnd_ctu_platform_info {
u32 flags;
};
struct rsnd_mix_platform_info {
u32 flags;
};
struct rsnd_dvc_platform_info { struct rsnd_dvc_platform_info {
u32 flags; u32 flags;
}; };
@ -68,6 +76,8 @@ struct rsnd_dvc_platform_info {
struct rsnd_dai_path_info { struct rsnd_dai_path_info {
struct rsnd_ssi_platform_info *ssi; struct rsnd_ssi_platform_info *ssi;
struct rsnd_src_platform_info *src; struct rsnd_src_platform_info *src;
struct rsnd_ctu_platform_info *ctu;
struct rsnd_mix_platform_info *mix;
struct rsnd_dvc_platform_info *dvc; struct rsnd_dvc_platform_info *dvc;
}; };
@ -93,6 +103,10 @@ struct rcar_snd_info {
int ssi_info_nr; int ssi_info_nr;
struct rsnd_src_platform_info *src_info; struct rsnd_src_platform_info *src_info;
int src_info_nr; int src_info_nr;
struct rsnd_ctu_platform_info *ctu_info;
int ctu_info_nr;
struct rsnd_mix_platform_info *mix_info;
int mix_info_nr;
struct rsnd_dvc_platform_info *dvc_info; struct rsnd_dvc_platform_info *dvc_info;
int dvc_info_nr; int dvc_info_nr;
struct rsnd_dai_platform_info *dai_info; struct rsnd_dai_platform_info *dai_info;

View File

@ -1366,7 +1366,7 @@ static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
{ {
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona; struct arizona *arizona = priv->arizona;
struct reg_default dac_comp[] = { struct reg_sequence dac_comp[] = {
{ 0x80, 0x3 }, { 0x80, 0x3 },
{ ARIZONA_DAC_COMP_1, 0 }, { ARIZONA_DAC_COMP_1, 0 },
{ ARIZONA_DAC_COMP_2, 0 }, { ARIZONA_DAC_COMP_2, 0 },

View File

@ -241,7 +241,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs35l32 = {
}; };
/* Current and threshold powerup sequence Pg37 in datasheet */ /* Current and threshold powerup sequence Pg37 in datasheet */
static const struct reg_default cs35l32_monitor_patch[] = { static const struct reg_sequence cs35l32_monitor_patch[] = {
{ 0x00, 0x99 }, { 0x00, 0x99 },
{ 0x48, 0x17 }, { 0x48, 0x17 },

View File

@ -1067,7 +1067,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs42l52 = {
}; };
/* Current and threshold powerup sequence Pg37 */ /* Current and threshold powerup sequence Pg37 */
static const struct reg_default cs42l52_threshold_patch[] = { static const struct reg_sequence cs42l52_threshold_patch[] = {
{ 0x00, 0x99 }, { 0x00, 0x99 },
{ 0x3E, 0xBA }, { 0x3E, 0xBA },

View File

@ -1182,7 +1182,7 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
#if IS_ENABLED(CONFIG_I2C) #if IS_ENABLED(CONFIG_I2C)
static const struct reg_default da7210_regmap_i2c_patch[] = { static const struct reg_sequence da7210_regmap_i2c_patch[] = {
/* System controller master disable */ /* System controller master disable */
{ DA7210_STARTUP1, 0x00 }, { DA7210_STARTUP1, 0x00 },
@ -1268,7 +1268,7 @@ static struct i2c_driver da7210_i2c_driver = {
#if defined(CONFIG_SPI_MASTER) #if defined(CONFIG_SPI_MASTER)
static const struct reg_default da7210_regmap_spi_patch[] = { static const struct reg_sequence da7210_regmap_spi_patch[] = {
/* Dummy read to give two pulses over nCS for SPI */ /* Dummy read to give two pulses over nCS for SPI */
{ DA7210_AUX2, 0x00 }, { DA7210_AUX2, 0x00 },
{ DA7210_AUX2, 0x00 }, { DA7210_AUX2, 0x00 },

View File

@ -11,38 +11,98 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/regmap.h>
#include "rl6231.h" #include "rl6231.h"
/** /**
* rl6231_calc_dmic_clk - Calculate the parameter of dmic. * rl6231_get_pre_div - Return the value of pre divider.
*
* @map: map for setting.
* @reg: register.
* @sft: shift.
*
* Return the value of pre divider from given register value.
* Return negative error code for unexpected register value.
*/
int rl6231_get_pre_div(struct regmap *map, unsigned int reg, int sft)
{
int pd, val;
regmap_read(map, reg, &val);
val = (val >> sft) & 0x7;
switch (val) {
case 0:
case 1:
case 2:
case 3:
pd = val + 1;
break;
case 4:
pd = 6;
break;
case 5:
pd = 8;
break;
case 6:
pd = 12;
break;
case 7:
pd = 16;
break;
default:
pd = -EINVAL;
break;
}
return pd;
}
EXPORT_SYMBOL_GPL(rl6231_get_pre_div);
/**
* rl6231_calc_dmic_clk - Calculate the frequency divider parameter of dmic.
* *
* @rate: base clock rate. * @rate: base clock rate.
* *
* Choose dmic clock between 1MHz and 3MHz. * Choose divider parameter that gives the highest possible DMIC frequency in
* It is better for clock to approximate 3MHz. * 1MHz - 3MHz range.
*/ */
int rl6231_calc_dmic_clk(int rate) int rl6231_calc_dmic_clk(int rate)
{ {
int div[] = {2, 3, 4, 6, 8, 12}, idx = -EINVAL; int div[] = {2, 3, 4, 6, 8, 12};
int i, red, bound, temp; int i;
red = 3000000 * 12; if (rate < 1000000 * div[0]) {
for (i = 0; i < ARRAY_SIZE(div); i++) { pr_warn("Base clock rate %d is too low\n", rate);
bound = div[i] * 3000000; return -EINVAL;
if (rate > bound)
continue;
temp = bound - rate;
if (temp < red) {
red = temp;
idx = i;
}
} }
return idx; for (i = 0; i < ARRAY_SIZE(div); i++) {
/* find divider that gives DMIC frequency below 3MHz */
if (3000000 * div[i] >= rate)
return i;
}
pr_warn("Base clock rate %d is too high\n", rate);
return -EINVAL;
} }
EXPORT_SYMBOL_GPL(rl6231_calc_dmic_clk); EXPORT_SYMBOL_GPL(rl6231_calc_dmic_clk);
struct pll_calc_map {
unsigned int pll_in;
unsigned int pll_out;
int k;
int n;
int m;
bool m_bp;
};
static const struct pll_calc_map pll_preset_table[] = {
{19200000, 24576000, 3, 30, 3, false},
};
/** /**
* rl6231_pll_calc - Calcualte PLL M/N/K code. * rl6231_pll_calc - Calcualte PLL M/N/K code.
* @freq_in: external clock provided to codec. * @freq_in: external clock provided to codec.
@ -57,7 +117,7 @@ int rl6231_pll_calc(const unsigned int freq_in,
const unsigned int freq_out, struct rl6231_pll_code *pll_code) const unsigned int freq_out, struct rl6231_pll_code *pll_code)
{ {
int max_n = RL6231_PLL_N_MAX, max_m = RL6231_PLL_M_MAX; int max_n = RL6231_PLL_N_MAX, max_m = RL6231_PLL_M_MAX;
int k, red, n_t, pll_out, in_t, out_t; int i, k, red, n_t, pll_out, in_t, out_t;
int n = 0, m = 0, m_t = 0; int n = 0, m = 0, m_t = 0;
int red_t = abs(freq_out - freq_in); int red_t = abs(freq_out - freq_in);
bool bypass = false; bool bypass = false;
@ -65,6 +125,18 @@ int rl6231_pll_calc(const unsigned int freq_in,
if (RL6231_PLL_INP_MAX < freq_in || RL6231_PLL_INP_MIN > freq_in) if (RL6231_PLL_INP_MAX < freq_in || RL6231_PLL_INP_MIN > freq_in)
return -EINVAL; return -EINVAL;
for (i = 0; i < ARRAY_SIZE(pll_preset_table); i++) {
if (freq_in == pll_preset_table[i].pll_in &&
freq_out == pll_preset_table[i].pll_out) {
k = pll_preset_table[i].k;
m = pll_preset_table[i].m;
n = pll_preset_table[i].n;
bypass = pll_preset_table[i].m_bp;
pr_debug("Use preset PLL parameter table\n");
goto code_find;
}
}
k = 100000000 / freq_out - 2; k = 100000000 / freq_out - 2;
if (k > RL6231_PLL_K_MAX) if (k > RL6231_PLL_K_MAX)
k = RL6231_PLL_K_MAX; k = RL6231_PLL_K_MAX;

View File

@ -30,5 +30,6 @@ int rl6231_calc_dmic_clk(int rate);
int rl6231_pll_calc(const unsigned int freq_in, int rl6231_pll_calc(const unsigned int freq_in,
const unsigned int freq_out, struct rl6231_pll_code *pll_code); const unsigned int freq_out, struct rl6231_pll_code *pll_code);
int rl6231_get_clk_info(int sclk, int rate); int rl6231_get_clk_info(int sclk, int rate);
int rl6231_get_pre_div(struct regmap *map, unsigned int reg, int sft);
#endif /* __RL6231_H__ */ #endif /* __RL6231_H__ */

View File

@ -1108,7 +1108,7 @@ static const struct acpi_device_id rt286_acpi_match[] = {
}; };
MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); MODULE_DEVICE_TABLE(acpi, rt286_acpi_match);
static struct dmi_system_id force_combo_jack_table[] = { static const struct dmi_system_id force_combo_jack_table[] = {
{ {
.ident = "Intel Wilson Beach", .ident = "Intel Wilson Beach",
.matches = { .matches = {
@ -1118,7 +1118,7 @@ static struct dmi_system_id force_combo_jack_table[] = {
{ } { }
}; };
static struct dmi_system_id dmi_dell_dino[] = { static const struct dmi_system_id dmi_dell_dino[] = {
{ {
.ident = "Dell Dino", .ident = "Dell Dino",
.matches = { .matches = {
@ -1157,7 +1157,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
} }
if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) { if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) {
dev_err(&i2c->dev, dev_err(&i2c->dev,
"Device with ID register %x is not rt286\n", val); "Device with ID register %#x is not rt286\n", val);
return -ENODEV; return -ENODEV;
} }

View File

@ -51,7 +51,7 @@ static const struct regmap_range_cfg rt5640_ranges[] = {
.window_len = 0x1, }, .window_len = 0x1, },
}; };
static const struct reg_default init_list[] = { static const struct reg_sequence init_list[] = {
{RT5640_PR_BASE + 0x3d, 0x3600}, {RT5640_PR_BASE + 0x3d, 0x3600},
{RT5640_PR_BASE + 0x12, 0x0aa8}, {RT5640_PR_BASE + 0x12, 0x0aa8},
{RT5640_PR_BASE + 0x14, 0x0aaa}, {RT5640_PR_BASE + 0x14, 0x0aaa},
@ -459,10 +459,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{ {
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
int idx = -EINVAL; int idx, rate;
idx = rl6231_calc_dmic_clk(rt5640->sysclk);
rate = rt5640->sysclk / rl6231_get_pre_div(rt5640->regmap,
RT5640_ADDA_CLK1, RT5640_I2S_PD1_SFT);
idx = rl6231_calc_dmic_clk(rate);
if (idx < 0) if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n"); dev_err(codec->dev, "Failed to set DMIC clock\n");
else else

View File

@ -55,7 +55,7 @@ static const struct regmap_range_cfg rt5645_ranges[] = {
}, },
}; };
static const struct reg_default init_list[] = { static const struct reg_sequence init_list[] = {
{RT5645_PR_BASE + 0x3d, 0x3600}, {RT5645_PR_BASE + 0x3d, 0x3600},
{RT5645_PR_BASE + 0x1c, 0xfd20}, {RT5645_PR_BASE + 0x1c, 0xfd20},
{RT5645_PR_BASE + 0x20, 0x611f}, {RT5645_PR_BASE + 0x20, 0x611f},
@ -64,7 +64,7 @@ static const struct reg_default init_list[] = {
}; };
#define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list) #define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list)
static const struct reg_default rt5650_init_list[] = { static const struct reg_sequence rt5650_init_list[] = {
{0xf6, 0x0100}, {0xf6, 0x0100},
}; };
@ -545,10 +545,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{ {
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
int idx = -EINVAL; int idx, rate;
idx = rl6231_calc_dmic_clk(rt5645->sysclk);
rate = rt5645->sysclk / rl6231_get_pre_div(rt5645->regmap,
RT5645_ADDA_CLK1, RT5645_I2S_PD1_SFT);
idx = rl6231_calc_dmic_clk(rate);
if (idx < 0) if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n"); dev_err(codec->dev, "Failed to set DMIC clock\n");
else else

View File

@ -46,7 +46,7 @@ static const struct regmap_range_cfg rt5651_ranges[] = {
.window_len = 0x1, }, .window_len = 0x1, },
}; };
static const struct reg_default init_list[] = { static const struct reg_sequence init_list[] = {
{RT5651_PR_BASE + 0x3d, 0x3e00}, {RT5651_PR_BASE + 0x3d, 0x3e00},
}; };
@ -378,10 +378,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{ {
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
int idx = -EINVAL; int idx, rate;
idx = rl6231_calc_dmic_clk(rt5651->sysclk);
rate = rt5651->sysclk / rl6231_get_pre_div(rt5651->regmap,
RT5651_ADDA_CLK1, RT5651_I2S_PD1_SFT);
idx = rl6231_calc_dmic_clk(rate);
if (idx < 0) if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n"); dev_err(codec->dev, "Failed to set DMIC clock\n");
else else

View File

@ -51,7 +51,7 @@ static const struct regmap_range_cfg rt5670_ranges[] = {
.window_len = 0x1, }, .window_len = 0x1, },
}; };
static const struct reg_default init_list[] = { static const struct reg_sequence init_list[] = {
{ RT5670_PR_BASE + 0x14, 0x9a8a }, { RT5670_PR_BASE + 0x14, 0x9a8a },
{ RT5670_PR_BASE + 0x38, 0x3ba1 }, { RT5670_PR_BASE + 0x38, 0x3ba1 },
{ RT5670_PR_BASE + 0x3d, 0x3640 }, { RT5670_PR_BASE + 0x3d, 0x3640 },
@ -683,10 +683,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{ {
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
int idx = -EINVAL; int idx, rate;
idx = rl6231_calc_dmic_clk(rt5670->sysclk);
rate = rt5670->sysclk / rl6231_get_pre_div(rt5670->regmap,
RT5670_ADDA_CLK1, RT5670_I2S_PD1_SFT);
idx = rl6231_calc_dmic_clk(rate);
if (idx < 0) if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n"); dev_err(codec->dev, "Failed to set DMIC clock\n");
else else

View File

@ -54,7 +54,7 @@ static const struct regmap_range_cfg rt5677_ranges[] = {
}, },
}; };
static const struct reg_default init_list[] = { static const struct reg_sequence init_list[] = {
{RT5677_ASRC_12, 0x0018}, {RT5677_ASRC_12, 0x0018},
{RT5677_PR_BASE + 0x3d, 0x364d}, {RT5677_PR_BASE + 0x3d, 0x364d},
{RT5677_PR_BASE + 0x17, 0x4fc0}, {RT5677_PR_BASE + 0x17, 0x4fc0},
@ -917,8 +917,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{ {
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
int idx = rl6231_calc_dmic_clk(rt5677->lrck[RT5677_AIF1] << 8); int idx, rate;
rate = rt5677->sysclk / rl6231_get_pre_div(rt5677->regmap,
RT5677_CLK_TREE_CTRL1, RT5677_I2S_PD1_SFT);
idx = rl6231_calc_dmic_clk(rate);
if (idx < 0) if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n"); dev_err(codec->dev, "Failed to set DMIC clock\n");
else else

View File

@ -1668,7 +1668,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
static const struct reg_default aic3007_class_d[] = { static const struct reg_sequence aic3007_class_d[] = {
/* Class-D speaker driver init; datasheet p. 46 */ /* Class-D speaker driver init; datasheet p. 46 */
{ AIC3X_PAGE_SELECT, 0x0D }, { AIC3X_PAGE_SELECT, 0x0D },
{ 0xD, 0x0D }, { 0xD, 0x0D },

View File

@ -897,7 +897,7 @@ static bool wm2200_readable_register(struct device *dev, unsigned int reg)
} }
} }
static const struct reg_default wm2200_reva_patch[] = { static const struct reg_sequence wm2200_reva_patch[] = {
{ 0x07, 0x0003 }, { 0x07, 0x0003 },
{ 0x102, 0x0200 }, { 0x102, 0x0200 },
{ 0x203, 0x0084 }, { 0x203, 0x0084 },

View File

@ -1247,7 +1247,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
{ "PWM2", NULL, "PWM2 Driver" }, { "PWM2", NULL, "PWM2 Driver" },
}; };
static const struct reg_default wm5100_reva_patches[] = { static const struct reg_sequence wm5100_reva_patches[] = {
{ WM5100_AUDIO_IF_1_10, 0 }, { WM5100_AUDIO_IF_1_10, 0 },
{ WM5100_AUDIO_IF_1_11, 1 }, { WM5100_AUDIO_IF_1_11, 1 },
{ WM5100_AUDIO_IF_1_12, 2 }, { WM5100_AUDIO_IF_1_12, 2 },

View File

@ -3495,7 +3495,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
}; };
/* Improve power consumption for IN4 DC measurement mode */ /* Improve power consumption for IN4 DC measurement mode */
static const struct reg_default wm8962_dc_measure[] = { static const struct reg_sequence wm8962_dc_measure[] = {
{ 0xfd, 0x1 }, { 0xfd, 0x1 },
{ 0xcc, 0x40 }, { 0xcc, 0x40 },
{ 0xfd, 0 }, { 0xfd, 0 },

View File

@ -1595,7 +1595,7 @@ static int wm8993_resume(struct snd_soc_codec *codec)
#endif #endif
/* Tune DC servo configuration */ /* Tune DC servo configuration */
static const struct reg_default wm8993_regmap_patch[] = { static const struct reg_sequence wm8993_regmap_patch[] = {
{ 0x44, 3 }, { 0x44, 3 },
{ 0x56, 3 }, { 0x56, 3 },
{ 0x44, 0 }, { 0x44, 0 },

View File

@ -223,7 +223,6 @@ static struct platform_driver snd_rk_mc_driver = {
.probe = snd_rk_mc_probe, .probe = snd_rk_mc_probe,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE,
.pm = &snd_soc_pm_ops, .pm = &snd_soc_pm_ops,
.of_match_table = rockchip_max98090_of_match, .of_match_table = rockchip_max98090_of_match,
}, },

View File

@ -118,7 +118,7 @@ static int rk_init(struct snd_soc_pcm_runtime *runtime)
SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3, SND_JACK_BTN_2 | SND_JACK_BTN_3,
&headset_jack, NULL, 0); &headset_jack, NULL, 0);
if (!ret) { if (ret) {
dev_err(card->dev, "New Headset Jack failed! (%d)\n", ret); dev_err(card->dev, "New Headset Jack failed! (%d)\n", ret);
return ret; return ret;
} }
@ -212,7 +212,6 @@ static struct platform_driver snd_rk_mc_driver = {
.probe = snd_rk_mc_probe, .probe = snd_rk_mc_probe,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE,
.pm = &snd_soc_pm_ops, .pm = &snd_soc_pm_ops,
.of_match_table = rockchip_rt5645_of_match, .of_match_table = rockchip_rt5645_of_match,
}, },

View File

@ -1,4 +1,4 @@
snd-soc-rcar-objs := core.o gen.o dma.o src.o adg.o ssi.o dvc.o snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o src.o ctu.o mix.o dvc.o
obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o
snd-soc-rsrc-card-objs := rsrc-card.o snd-soc-rsrc-card-objs := rsrc-card.o

View File

@ -203,9 +203,9 @@ int rsnd_io_is_working(struct rsnd_dai_stream *io)
} }
/* /*
* settting function * ADINR function
*/ */
u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io) u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
{ {
struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
@ -227,6 +227,64 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
return adinr; return adinr;
} }
u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct device *dev = rsnd_priv_to_dev(priv);
u32 chan = runtime->channels;
switch (chan) {
case 1:
case 2:
case 4:
case 6:
case 8:
break;
default:
dev_warn(dev, "not supported channel\n");
chan = 0;
break;
}
return chan;
}
/*
* DALIGN function
*/
u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
{
struct rsnd_mod *src = rsnd_io_to_mod_src(io);
struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
struct rsnd_mod *target = src ? src : ssi;
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
u32 val = 0x76543210;
u32 mask = ~0;
mask <<= runtime->channels * 4;
val = val & mask;
switch (runtime->sample_bits) {
case 16:
val |= 0x67452301 & ~mask;
break;
case 32:
val |= 0x76543210 & ~mask;
break;
}
/*
* exchange channeles on SRC if possible,
* otherwise, R/L volume settings on DVC
* changes inverted channels
*/
if (mod == target)
return val;
else
return 0x76543210;
}
/* /*
* rsnd_dai functions * rsnd_dai functions
*/ */
@ -242,9 +300,9 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
if (val == __rsnd_mod_call_##func) { \ if (val == __rsnd_mod_call_##func) { \
called = 1; \ called = 1; \
ret = (mod)->ops->func(mod, io, param); \ ret = (mod)->ops->func(mod, io, param); \
mod->status = (mod->status & ~mask) + \
(add << __rsnd_mod_shift_##func); \
} \ } \
mod->status = (mod->status & ~mask) + \
(add << __rsnd_mod_shift_##func); \
dev_dbg(dev, "%s[%d] 0x%08x %s\n", \ dev_dbg(dev, "%s[%d] 0x%08x %s\n", \
rsnd_mod_name(mod), rsnd_mod_id(mod), mod->status, \ rsnd_mod_name(mod), rsnd_mod_id(mod), mod->status, \
called ? #func : ""); \ called ? #func : ""); \
@ -274,21 +332,21 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
static int rsnd_dai_connect(struct rsnd_mod *mod, static int rsnd_dai_connect(struct rsnd_mod *mod,
struct rsnd_dai_stream *io) struct rsnd_dai_stream *io)
{ {
struct rsnd_priv *priv;
struct device *dev;
if (!mod) if (!mod)
return -EIO; return -EIO;
if (io->mod[mod->type]) { priv = rsnd_mod_to_priv(mod);
struct rsnd_priv *priv = rsnd_mod_to_priv(mod); dev = rsnd_priv_to_dev(priv);
struct device *dev = rsnd_priv_to_dev(priv);
dev_err(dev, "%s[%d] is not empty\n",
rsnd_mod_name(mod),
rsnd_mod_id(mod));
return -EIO;
}
io->mod[mod->type] = mod; io->mod[mod->type] = mod;
dev_dbg(dev, "%s[%d] is connected to io (%s)\n",
rsnd_mod_name(mod), rsnd_mod_id(mod),
rsnd_io_is_play(io) ? "Playback" : "Capture");
return 0; return 0;
} }
@ -517,7 +575,7 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
.set_fmt = rsnd_soc_dai_set_fmt, .set_fmt = rsnd_soc_dai_set_fmt,
}; };
#define rsnd_path_parse(priv, io, type) \ #define rsnd_path_add(priv, io, type) \
({ \ ({ \
struct rsnd_mod *mod; \ struct rsnd_mod *mod; \
int ret = 0; \ int ret = 0; \
@ -533,7 +591,7 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
ret; \ ret; \
}) })
#define rsnd_path_break(priv, io, type) \ #define rsnd_path_remove(priv, io, type) \
{ \ { \
struct rsnd_mod *mod; \ struct rsnd_mod *mod; \
int id = -1; \ int id = -1; \
@ -547,6 +605,79 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
} \ } \
} }
void rsnd_path_parse(struct rsnd_priv *priv,
struct rsnd_dai_stream *io)
{
struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
struct rsnd_mod *src = rsnd_io_to_mod_src(io);
struct rsnd_mod *cmd;
struct device *dev = rsnd_priv_to_dev(priv);
u32 data;
/* Gen1 is not supported */
if (rsnd_is_gen1(priv))
return;
if (!mix && !dvc)
return;
if (mix) {
struct rsnd_dai *rdai;
int i;
u32 path[] = {
[0] = 0,
[1] = 1 << 0,
[2] = 0,
[3] = 0,
[4] = 0,
[5] = 1 << 8
};
/*
* it is assuming that integrater is well understanding about
* data path. Here doesn't check impossible connection,
* like src2 + src5
*/
data = 0;
for_each_rsnd_dai(rdai, priv, i) {
io = &rdai->playback;
if (mix == rsnd_io_to_mod_mix(io))
data |= path[rsnd_mod_id(src)];
io = &rdai->capture;
if (mix == rsnd_io_to_mod_mix(io))
data |= path[rsnd_mod_id(src)];
}
/*
* We can't use ctu = rsnd_io_ctu() here.
* Since, ID of dvc/mix are 0 or 1 (= same as CMD number)
* but ctu IDs are 0 - 7 (= CTU00 - CTU13)
*/
cmd = mix;
} else {
u32 path[] = {
[0] = 0x30000,
[1] = 0x30001,
[2] = 0x40000,
[3] = 0x10000,
[4] = 0x20000,
[5] = 0x40100
};
data = path[rsnd_mod_id(src)];
cmd = dvc;
}
dev_dbg(dev, "ctu/mix path = 0x%08x", data);
rsnd_mod_write(cmd, CMD_ROUTE_SLCT, data);
rsnd_mod_write(cmd, CMD_CTRL, 0x10);
}
static int rsnd_path_init(struct rsnd_priv *priv, static int rsnd_path_init(struct rsnd_priv *priv,
struct rsnd_dai *rdai, struct rsnd_dai *rdai,
struct rsnd_dai_stream *io) struct rsnd_dai_stream *io)
@ -564,18 +695,28 @@ static int rsnd_path_init(struct rsnd_priv *priv,
* using fixed path. * using fixed path.
*/ */
/* SRC */ /* SSI */
ret = rsnd_path_parse(priv, io, src); ret = rsnd_path_add(priv, io, ssi);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* SSI */ /* SRC */
ret = rsnd_path_parse(priv, io, ssi); ret = rsnd_path_add(priv, io, src);
if (ret < 0)
return ret;
/* CTU */
ret = rsnd_path_add(priv, io, ctu);
if (ret < 0)
return ret;
/* MIX */
ret = rsnd_path_add(priv, io, mix);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* DVC */ /* DVC */
ret = rsnd_path_parse(priv, io, dvc); ret = rsnd_path_add(priv, io, dvc);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -589,13 +730,15 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
struct device_node *dai_node, *dai_np; struct device_node *dai_node, *dai_np;
struct device_node *ssi_node, *ssi_np; struct device_node *ssi_node, *ssi_np;
struct device_node *src_node, *src_np; struct device_node *src_node, *src_np;
struct device_node *ctu_node, *ctu_np;
struct device_node *mix_node, *mix_np;
struct device_node *dvc_node, *dvc_np; struct device_node *dvc_node, *dvc_np;
struct device_node *playback, *capture; struct device_node *playback, *capture;
struct rsnd_dai_platform_info *dai_info; struct rsnd_dai_platform_info *dai_info;
struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rcar_snd_info *info = rsnd_priv_to_info(priv);
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int nr, i; int nr, i;
int dai_i, ssi_i, src_i, dvc_i; int dai_i, ssi_i, src_i, ctu_i, mix_i, dvc_i;
if (!of_data) if (!of_data)
return; return;
@ -621,6 +764,8 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi");
src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src");
ctu_node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu");
mix_node = of_get_child_by_name(dev->of_node, "rcar_sound,mix");
dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc");
#define mod_parse(name) \ #define mod_parse(name) \
@ -657,6 +802,8 @@ if (name##_node) { \
mod_parse(ssi); mod_parse(ssi);
mod_parse(src); mod_parse(src);
mod_parse(ctu);
mod_parse(mix);
mod_parse(dvc); mod_parse(dvc);
of_node_put(playback); of_node_put(playback);
@ -1033,8 +1180,8 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
/* /*
* remove SRC/DVC from DAI, * remove SRC/DVC from DAI,
*/ */
rsnd_path_break(priv, io, src); rsnd_path_remove(priv, io, src);
rsnd_path_break(priv, io, dvc); rsnd_path_remove(priv, io, dvc);
/* /*
* fallback * fallback
@ -1069,6 +1216,8 @@ static int rsnd_probe(struct platform_device *pdev)
rsnd_dma_probe, rsnd_dma_probe,
rsnd_ssi_probe, rsnd_ssi_probe,
rsnd_src_probe, rsnd_src_probe,
rsnd_ctu_probe,
rsnd_mix_probe,
rsnd_dvc_probe, rsnd_dvc_probe,
rsnd_adg_probe, rsnd_adg_probe,
rsnd_dai_probe, rsnd_dai_probe,
@ -1164,6 +1313,8 @@ static int rsnd_remove(struct platform_device *pdev)
struct rsnd_priv *priv) = { struct rsnd_priv *priv) = {
rsnd_ssi_remove, rsnd_ssi_remove,
rsnd_src_remove, rsnd_src_remove,
rsnd_ctu_remove,
rsnd_mix_remove,
rsnd_dvc_remove, rsnd_dvc_remove,
}; };
int ret = 0, i; int ret = 0, i;

171
sound/soc/sh/rcar/ctu.c Normal file
View File

@ -0,0 +1,171 @@
/*
* ctu.c
*
* Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "rsnd.h"
#define CTU_NAME_SIZE 16
#define CTU_NAME "ctu"
struct rsnd_ctu {
struct rsnd_ctu_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
};
#define rsnd_ctu_nr(priv) ((priv)->ctu_nr)
#define for_each_rsnd_ctu(pos, priv, i) \
for ((i) = 0; \
((i) < rsnd_ctu_nr(priv)) && \
((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \
i++)
#define rsnd_ctu_initialize_lock(mod) __rsnd_ctu_initialize_lock(mod, 1)
#define rsnd_ctu_initialize_unlock(mod) __rsnd_ctu_initialize_lock(mod, 0)
static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable)
{
rsnd_mod_write(mod, CTU_CTUIR, enable);
}
static int rsnd_ctu_init(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
rsnd_mod_hw_start(mod);
rsnd_ctu_initialize_lock(mod);
rsnd_mod_write(mod, CTU_ADINR, rsnd_get_adinr_chan(mod, io));
rsnd_ctu_initialize_unlock(mod);
return 0;
}
static int rsnd_ctu_quit(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
rsnd_mod_hw_stop(mod);
return 0;
}
static struct rsnd_mod_ops rsnd_ctu_ops = {
.name = CTU_NAME,
.init = rsnd_ctu_init,
.quit = rsnd_ctu_quit,
};
struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
{
if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
id = 0;
return &((struct rsnd_ctu *)(priv->ctu) + id)->mod;
}
static void rsnd_of_parse_ctu(struct platform_device *pdev,
const struct rsnd_of_data *of_data,
struct rsnd_priv *priv)
{
struct device_node *node;
struct rsnd_ctu_platform_info *ctu_info;
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
struct device *dev = &pdev->dev;
int nr;
if (!of_data)
return;
node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu");
if (!node)
return;
nr = of_get_child_count(node);
if (!nr)
goto rsnd_of_parse_ctu_end;
ctu_info = devm_kzalloc(dev,
sizeof(struct rsnd_ctu_platform_info) * nr,
GFP_KERNEL);
if (!ctu_info) {
dev_err(dev, "ctu info allocation error\n");
goto rsnd_of_parse_ctu_end;
}
info->ctu_info = ctu_info;
info->ctu_info_nr = nr;
rsnd_of_parse_ctu_end:
of_node_put(node);
}
int rsnd_ctu_probe(struct platform_device *pdev,
const struct rsnd_of_data *of_data,
struct rsnd_priv *priv)
{
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_ctu *ctu;
struct clk *clk;
char name[CTU_NAME_SIZE];
int i, nr, ret;
/* This driver doesn't support Gen1 at this point */
if (rsnd_is_gen1(priv)) {
dev_warn(dev, "CTU is not supported on Gen1\n");
return -EINVAL;
}
rsnd_of_parse_ctu(pdev, of_data, priv);
nr = info->ctu_info_nr;
if (!nr)
return 0;
ctu = devm_kzalloc(dev, sizeof(*ctu) * nr, GFP_KERNEL);
if (!ctu)
return -ENOMEM;
priv->ctu_nr = nr;
priv->ctu = ctu;
for_each_rsnd_ctu(ctu, priv, i) {
/*
* CTU00, CTU01, CTU02, CTU03 => CTU0
* CTU10, CTU11, CTU12, CTU13 => CTU1
*/
snprintf(name, CTU_NAME_SIZE, "%s.%d",
CTU_NAME, i / 4);
clk = devm_clk_get(dev, name);
if (IS_ERR(clk))
return PTR_ERR(clk);
ctu->info = &info->ctu_info[i];
ret = rsnd_mod_init(priv, &ctu->mod, &rsnd_ctu_ops,
clk, RSND_MOD_CTU, i);
if (ret)
return ret;
}
return 0;
}
void rsnd_ctu_remove(struct platform_device *pdev,
struct rsnd_priv *priv)
{
struct rsnd_ctu *ctu;
int i;
for_each_rsnd_ctu(ctu, priv, i) {
rsnd_mod_quit(&ctu->mod);
}
}

View File

@ -27,6 +27,15 @@ struct rsnd_dma_ctrl {
int dmapp_num; int dmapp_num;
}; };
struct rsnd_dma_ops {
char *name;
void (*start)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
void (*stop)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
int (*init)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id,
struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
void (*quit)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
};
#define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma) #define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma)
/* /*
@ -168,7 +177,7 @@ static int rsnd_dmaen_init(struct rsnd_dai_stream *io,
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
dmaen->chan = dma_request_channel(mask, shdma_chan_filter, dmaen->chan = dma_request_channel(mask, shdma_chan_filter,
(void *)id); (void *)(uintptr_t)id);
} }
if (IS_ERR_OR_NULL(dmaen->chan)) { if (IS_ERR_OR_NULL(dmaen->chan)) {
dmaen->chan = NULL; dmaen->chan = NULL;
@ -182,7 +191,8 @@ static int rsnd_dmaen_init(struct rsnd_dai_stream *io,
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
dev_dbg(dev, "dma : %pad -> %pad\n", dev_dbg(dev, "%s %pad -> %pad\n",
dma->ops->name,
&cfg.src_addr, &cfg.dst_addr); &cfg.src_addr, &cfg.dst_addr);
ret = dmaengine_slave_config(dmaen->chan, &cfg); ret = dmaengine_slave_config(dmaen->chan, &cfg);
@ -215,6 +225,7 @@ static void rsnd_dmaen_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
} }
static struct rsnd_dma_ops rsnd_dmaen_ops = { static struct rsnd_dma_ops rsnd_dmaen_ops = {
.name = "audmac",
.start = rsnd_dmaen_start, .start = rsnd_dmaen_start,
.stop = rsnd_dmaen_stop, .stop = rsnd_dmaen_stop,
.init = rsnd_dmaen_init, .init = rsnd_dmaen_init,
@ -360,6 +371,7 @@ static int rsnd_dmapp_init(struct rsnd_dai_stream *io,
} }
static struct rsnd_dma_ops rsnd_dmapp_ops = { static struct rsnd_dma_ops rsnd_dmapp_ops = {
.name = "audmac-pp",
.start = rsnd_dmapp_start, .start = rsnd_dmapp_start,
.stop = rsnd_dmapp_stop, .stop = rsnd_dmapp_stop,
.init = rsnd_dmapp_init, .init = rsnd_dmapp_init,
@ -414,7 +426,9 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU); phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU);
int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod);
int use_src = !!rsnd_io_to_mod_src(io); int use_src = !!rsnd_io_to_mod_src(io);
int use_dvc = !!rsnd_io_to_mod_dvc(io); int use_cmd = !!rsnd_io_to_mod_dvc(io) ||
!!rsnd_io_to_mod_mix(io) ||
!!rsnd_io_to_mod_ctu(io);
int id = rsnd_mod_id(mod); int id = rsnd_mod_id(mod);
struct dma_addr { struct dma_addr {
dma_addr_t out_addr; dma_addr_t out_addr;
@ -452,7 +466,7 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
}; };
/* it shouldn't happen */ /* it shouldn't happen */
if (use_dvc && !use_src) if (use_cmd && !use_src)
dev_err(dev, "DVC is selected without SRC\n"); dev_err(dev, "DVC is selected without SRC\n");
/* use SSIU or SSI ? */ /* use SSIU or SSI ? */
@ -460,8 +474,8 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
is_ssi++; is_ssi++;
return (is_from) ? return (is_from) ?
dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr : dma_addrs[is_ssi][is_play][use_src + use_cmd].out_addr :
dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; dma_addrs[is_ssi][is_play][use_src + use_cmd].in_addr;
} }
static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io, static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
@ -482,7 +496,7 @@ static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
return rsnd_gen2_dma_addr(io, mod, is_play, is_from); return rsnd_gen2_dma_addr(io, mod, is_play, is_from);
} }
#define MOD_MAX 4 /* MEM/SSI/SRC/DVC */ #define MOD_MAX (RSND_MOD_MAX + 1) /* +Memory */
static void rsnd_dma_of_path(struct rsnd_dma *dma, static void rsnd_dma_of_path(struct rsnd_dma *dma,
struct rsnd_dai_stream *io, struct rsnd_dai_stream *io,
int is_play, int is_play,
@ -492,55 +506,81 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma,
struct rsnd_mod *this = rsnd_dma_to_mod(dma); struct rsnd_mod *this = rsnd_dma_to_mod(dma);
struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
struct rsnd_mod *src = rsnd_io_to_mod_src(io); struct rsnd_mod *src = rsnd_io_to_mod_src(io);
struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io);
struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
struct rsnd_mod *mod[MOD_MAX]; struct rsnd_mod *mod[MOD_MAX];
int i, index; struct rsnd_mod *mod_start, *mod_end;
struct rsnd_priv *priv = rsnd_mod_to_priv(this);
struct device *dev = rsnd_priv_to_dev(priv);
int nr, i;
if (!ssi)
return;
for (i = 0; i < MOD_MAX; i++) nr = 0;
for (i = 0; i < MOD_MAX; i++) {
mod[i] = NULL; mod[i] = NULL;
nr += !!rsnd_io_to_mod(io, i);
/*
* in play case...
*
* src -> dst
*
* mem -> SSI
* mem -> SRC -> SSI
* mem -> SRC -> DVC -> SSI
*/
mod[0] = NULL; /* for "mem" */
index = 1;
for (i = 1; i < MOD_MAX; i++) {
if (!src) {
mod[i] = ssi;
} else if (!dvc) {
mod[i] = src;
src = NULL;
} else {
if ((!is_play) && (this == src))
this = dvc;
mod[i] = (is_play) ? src : dvc;
i++;
mod[i] = (is_play) ? dvc : src;
src = NULL;
dvc = NULL;
}
if (mod[i] == this)
index = i;
if (mod[i] == ssi)
break;
} }
if (is_play) { /*
*mod_from = mod[index - 1]; * [S] -*-> [E]
*mod_to = mod[index]; * [S] -*-> SRC -o-> [E]
* [S] -*-> SRC -> DVC -o-> [E]
* [S] -*-> SRC -> CTU -> MIX -> DVC -o-> [E]
*
* playback [S] = mem
* [E] = SSI
*
* capture [S] = SSI
* [E] = mem
*
* -*-> Audio DMAC
* -o-> Audio DMAC peri peri
*/
mod_start = (is_play) ? NULL : ssi;
mod_end = (is_play) ? ssi : NULL;
mod[0] = mod_start;
for (i = 1; i < nr; i++) {
if (src) {
mod[i] = src;
src = NULL;
} else if (ctu) {
mod[i] = ctu;
ctu = NULL;
} else if (mix) {
mod[i] = mix;
mix = NULL;
} else if (dvc) {
mod[i] = dvc;
dvc = NULL;
}
}
mod[i] = mod_end;
/*
* | SSI | SRC |
* -------------+-----+-----+
* is_play | o | * |
* !is_play | * | o |
*/
if ((this == ssi) == (is_play)) {
*mod_from = mod[nr - 1];
*mod_to = mod[nr];
} else { } else {
*mod_from = mod[index]; *mod_from = mod[0];
*mod_to = mod[index - 1]; *mod_to = mod[1];
}
dev_dbg(dev, "module connection (this is %s[%d])\n",
rsnd_mod_name(this), rsnd_mod_id(this));
for (i = 0; i <= nr; i++) {
dev_dbg(dev, " %s[%d]%s\n",
rsnd_mod_name(mod[i]), rsnd_mod_id(mod[i]),
(mod[i] == *mod_from) ? " from" :
(mod[i] == *mod_to) ? " to" : "");
} }
} }
@ -568,10 +608,11 @@ void rsnd_dma_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id) int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id)
{ {
struct rsnd_mod *mod_from; struct rsnd_mod *mod_from = NULL;
struct rsnd_mod *mod_to; struct rsnd_mod *mod_to = NULL;
struct rsnd_priv *priv = rsnd_io_to_priv(io); struct rsnd_priv *priv = rsnd_io_to_priv(io);
struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
struct device *dev = rsnd_priv_to_dev(priv);
int is_play = rsnd_io_is_play(io); int is_play = rsnd_io_is_play(io);
/* /*
@ -598,6 +639,11 @@ int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id)
if (rsnd_is_gen1(priv)) if (rsnd_is_gen1(priv))
dma->ops = &rsnd_dmaen_ops; dma->ops = &rsnd_dmaen_ops;
dev_dbg(dev, "%s %s[%d] -> %s[%d]\n",
dma->ops->name,
rsnd_mod_name(mod_from), rsnd_mod_id(mod_from),
rsnd_mod_name(mod_to), rsnd_mod_id(mod_to));
return dma->ops->init(io, dma, id, mod_from, mod_to); return dma->ops->init(io, dma, id, mod_from, mod_to);
} }

View File

@ -24,6 +24,7 @@ struct rsnd_dvc {
struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */ struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */
}; };
#define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
#define rsnd_dvc_of_node(priv) \ #define rsnd_dvc_of_node(priv) \
of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,dvc") of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,dvc")
@ -63,6 +64,19 @@ static const char * const dvc_ramp_rate[] = {
"0.125 dB/8192 steps", /* 10111 */ "0.125 dB/8192 steps", /* 10111 */
}; };
static void rsnd_dvc_soft_reset(struct rsnd_mod *mod)
{
rsnd_mod_write(mod, DVC_SWRSR, 0);
rsnd_mod_write(mod, DVC_SWRSR, 1);
}
#define rsnd_dvc_initialize_lock(mod) __rsnd_dvc_initialize_lock(mod, 1)
#define rsnd_dvc_initialize_unlock(mod) __rsnd_dvc_initialize_lock(mod, 0)
static void __rsnd_dvc_initialize_lock(struct rsnd_mod *mod, u32 enable)
{
rsnd_mod_write(mod, DVC_DVUIR, enable);
}
static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io, static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
struct rsnd_mod *mod) struct rsnd_mod *mod)
{ {
@ -135,49 +149,24 @@ static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod,
return 0; return 0;
} }
static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, static int rsnd_dvc_init(struct rsnd_mod *mod,
struct rsnd_dai_stream *io, struct rsnd_dai_stream *io,
struct rsnd_priv *priv) struct rsnd_priv *priv)
{ {
struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); rsnd_mod_hw_start(mod);
struct device *dev = rsnd_priv_to_dev(priv);
int dvc_id = rsnd_mod_id(dvc_mod);
int src_id = rsnd_mod_id(src_mod);
u32 route[] = {
[0] = 0x30000,
[1] = 0x30001,
[2] = 0x40000,
[3] = 0x10000,
[4] = 0x20000,
[5] = 0x40100
};
if (src_id >= ARRAY_SIZE(route)) { rsnd_dvc_soft_reset(mod);
dev_err(dev, "DVC%d isn't connected to SRC%d\n", dvc_id, src_id);
return -EINVAL;
}
rsnd_mod_hw_start(dvc_mod); rsnd_dvc_initialize_lock(mod);
/* rsnd_path_parse(priv, io);
* fixme
* it doesn't support CTU/MIX
*/
rsnd_mod_write(dvc_mod, CMD_ROUTE_SLCT, route[src_id]);
rsnd_mod_write(dvc_mod, DVC_SWRSR, 0); rsnd_mod_write(mod, DVC_ADINR, rsnd_get_adinr_bit(mod, io));
rsnd_mod_write(dvc_mod, DVC_SWRSR, 1);
rsnd_mod_write(dvc_mod, DVC_DVUIR, 1);
rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod, io));
/* ch0/ch1 Volume */ /* ch0/ch1 Volume */
rsnd_dvc_volume_update(io, dvc_mod); rsnd_dvc_volume_update(io, mod);
rsnd_mod_write(dvc_mod, DVC_DVUIR, 0); rsnd_adg_set_cmd_timsel_gen2(mod, io);
rsnd_adg_set_cmd_timsel_gen2(dvc_mod, io);
return 0; return 0;
} }
@ -195,6 +184,8 @@ static int rsnd_dvc_start(struct rsnd_mod *mod,
struct rsnd_dai_stream *io, struct rsnd_dai_stream *io,
struct rsnd_priv *priv) struct rsnd_priv *priv)
{ {
rsnd_dvc_initialize_unlock(mod);
rsnd_mod_write(mod, CMD_CTRL, 0x10); rsnd_mod_write(mod, CMD_CTRL, 0x10);
return 0; return 0;
@ -341,23 +332,21 @@ int rsnd_dvc_probe(struct platform_device *pdev,
char name[RSND_DVC_NAME_SIZE]; char name[RSND_DVC_NAME_SIZE];
int i, nr, ret; int i, nr, ret;
rsnd_of_parse_dvc(pdev, of_data, priv);
nr = info->dvc_info_nr;
if (!nr)
return 0;
/* This driver doesn't support Gen1 at this point */ /* This driver doesn't support Gen1 at this point */
if (rsnd_is_gen1(priv)) { if (rsnd_is_gen1(priv)) {
dev_warn(dev, "CMD is not supported on Gen1\n"); dev_warn(dev, "CMD is not supported on Gen1\n");
return -EINVAL; return -EINVAL;
} }
rsnd_of_parse_dvc(pdev, of_data, priv);
nr = info->dvc_info_nr;
if (!nr)
return 0;
dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL); dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL);
if (!dvc) { if (!dvc)
dev_err(dev, "CMD allocate failed\n");
return -ENOMEM; return -ENOMEM;
}
priv->dvc_nr = nr; priv->dvc_nr = nr;
priv->dvc = dvc; priv->dvc = dvc;

View File

@ -103,6 +103,22 @@ void rsnd_write(struct rsnd_priv *priv,
regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
} }
void rsnd_force_write(struct rsnd_priv *priv,
struct rsnd_mod *mod,
enum rsnd_reg reg, u32 data)
{
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
if (!rsnd_is_accessible_reg(priv, gen, reg))
return;
dev_dbg(dev, "w %s[%d] - %4d : %08x\n",
rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data);
regmap_fields_force_write(gen->regs[reg], rsnd_mod_id(mod), data);
}
void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
enum rsnd_reg reg, u32 mask, u32 data) enum rsnd_reg reg, u32 mask, u32 data)
{ {
@ -200,12 +216,13 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
/* FIXME: it needs SSI_MODE2/3 in the future */ /* FIXME: it needs SSI_MODE2/3 in the future */
RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80),
RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80), RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80),
RSND_GEN_M_REG(BUSIF_DALIGN, 0x8, 0x80), RSND_GEN_M_REG(SSI_BUSIF_DALIGN,0x8, 0x80),
RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80),
RSND_GEN_M_REG(INT_ENABLE, 0x18, 0x80), RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80),
}; };
struct rsnd_regmap_field_conf conf_scu[] = { struct rsnd_regmap_field_conf conf_scu[] = {
RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20), RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20),
RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20),
RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20),
RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20),
RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20), RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20),
@ -223,6 +240,18 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40),
RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40), RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40),
RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40),
RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100),
RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100),
RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40),
RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40),
RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40),
RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40),
RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40),
RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40),
RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40),
RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40),
RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40),
RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40),
RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100), RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100),
RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100), RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100),
RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100),

200
sound/soc/sh/rcar/mix.c Normal file
View File

@ -0,0 +1,200 @@
/*
* mix.c
*
* Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "rsnd.h"
#define MIX_NAME_SIZE 16
#define MIX_NAME "mix"
struct rsnd_mix {
struct rsnd_mix_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
};
#define rsnd_mix_nr(priv) ((priv)->mix_nr)
#define for_each_rsnd_mix(pos, priv, i) \
for ((i) = 0; \
((i) < rsnd_mix_nr(priv)) && \
((pos) = (struct rsnd_mix *)(priv)->mix + i); \
i++)
static void rsnd_mix_soft_reset(struct rsnd_mod *mod)
{
rsnd_mod_write(mod, MIX_SWRSR, 0);
rsnd_mod_write(mod, MIX_SWRSR, 1);
}
#define rsnd_mix_initialize_lock(mod) __rsnd_mix_initialize_lock(mod, 1)
#define rsnd_mix_initialize_unlock(mod) __rsnd_mix_initialize_lock(mod, 0)
static void __rsnd_mix_initialize_lock(struct rsnd_mod *mod, u32 enable)
{
rsnd_mod_write(mod, MIX_MIXIR, enable);
}
static void rsnd_mix_volume_update(struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
/* Disable MIX dB setting */
rsnd_mod_write(mod, MIX_MDBER, 0);
rsnd_mod_write(mod, MIX_MDBAR, 0);
rsnd_mod_write(mod, MIX_MDBBR, 0);
rsnd_mod_write(mod, MIX_MDBCR, 0);
rsnd_mod_write(mod, MIX_MDBDR, 0);
/* Enable MIX dB setting */
rsnd_mod_write(mod, MIX_MDBER, 1);
}
static int rsnd_mix_init(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
rsnd_mod_hw_start(mod);
rsnd_mix_soft_reset(mod);
rsnd_mix_initialize_lock(mod);
rsnd_mod_write(mod, MIX_ADINR, rsnd_get_adinr_chan(mod, io));
rsnd_path_parse(priv, io);
/* volume step */
rsnd_mod_write(mod, MIX_MIXMR, 0);
rsnd_mod_write(mod, MIX_MVPDR, 0);
rsnd_mix_volume_update(io, mod);
rsnd_mix_initialize_unlock(mod);
return 0;
}
static int rsnd_mix_quit(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
rsnd_mod_hw_stop(mod);
return 0;
}
static struct rsnd_mod_ops rsnd_mix_ops = {
.name = MIX_NAME,
.init = rsnd_mix_init,
.quit = rsnd_mix_quit,
};
struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id)
{
if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv)))
id = 0;
return &((struct rsnd_mix *)(priv->mix) + id)->mod;
}
static void rsnd_of_parse_mix(struct platform_device *pdev,
const struct rsnd_of_data *of_data,
struct rsnd_priv *priv)
{
struct device_node *node;
struct rsnd_mix_platform_info *mix_info;
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
struct device *dev = &pdev->dev;
int nr;
if (!of_data)
return;
node = of_get_child_by_name(dev->of_node, "rcar_sound,mix");
if (!node)
return;
nr = of_get_child_count(node);
if (!nr)
goto rsnd_of_parse_mix_end;
mix_info = devm_kzalloc(dev,
sizeof(struct rsnd_mix_platform_info) * nr,
GFP_KERNEL);
if (!mix_info) {
dev_err(dev, "mix info allocation error\n");
goto rsnd_of_parse_mix_end;
}
info->mix_info = mix_info;
info->mix_info_nr = nr;
rsnd_of_parse_mix_end:
of_node_put(node);
}
int rsnd_mix_probe(struct platform_device *pdev,
const struct rsnd_of_data *of_data,
struct rsnd_priv *priv)
{
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_mix *mix;
struct clk *clk;
char name[MIX_NAME_SIZE];
int i, nr, ret;
/* This driver doesn't support Gen1 at this point */
if (rsnd_is_gen1(priv)) {
dev_warn(dev, "MIX is not supported on Gen1\n");
return -EINVAL;
}
rsnd_of_parse_mix(pdev, of_data, priv);
nr = info->mix_info_nr;
if (!nr)
return 0;
mix = devm_kzalloc(dev, sizeof(*mix) * nr, GFP_KERNEL);
if (!mix)
return -ENOMEM;
priv->mix_nr = nr;
priv->mix = mix;
for_each_rsnd_mix(mix, priv, i) {
snprintf(name, MIX_NAME_SIZE, "%s.%d",
MIX_NAME, i);
clk = devm_clk_get(dev, name);
if (IS_ERR(clk))
return PTR_ERR(clk);
mix->info = &info->mix_info[i];
ret = rsnd_mod_init(priv, &mix->mod, &rsnd_mix_ops,
clk, RSND_MOD_MIX, i);
if (ret)
return ret;
}
return 0;
}
void rsnd_mix_remove(struct platform_device *pdev,
struct rsnd_priv *priv)
{
struct rsnd_mix *mix;
int i;
for_each_rsnd_mix(mix, priv, i) {
rsnd_mod_quit(&mix->mod);
}
}

View File

@ -47,6 +47,18 @@ enum rsnd_reg {
RSND_REG_SCU_SYS_STATUS0, RSND_REG_SCU_SYS_STATUS0,
RSND_REG_SCU_SYS_INT_EN0, RSND_REG_SCU_SYS_INT_EN0,
RSND_REG_CMD_ROUTE_SLCT, RSND_REG_CMD_ROUTE_SLCT,
RSND_REG_CTU_CTUIR,
RSND_REG_CTU_ADINR,
RSND_REG_MIX_SWRSR,
RSND_REG_MIX_MIXIR,
RSND_REG_MIX_ADINR,
RSND_REG_MIX_MIXMR,
RSND_REG_MIX_MVPDR,
RSND_REG_MIX_MDBAR,
RSND_REG_MIX_MDBBR,
RSND_REG_MIX_MDBCR,
RSND_REG_MIX_MDBDR,
RSND_REG_MIX_MDBER,
RSND_REG_DVC_SWRSR, RSND_REG_DVC_SWRSR,
RSND_REG_DVC_DVUIR, RSND_REG_DVC_DVUIR,
RSND_REG_DVC_ADINR, RSND_REG_DVC_ADINR,
@ -99,6 +111,7 @@ enum rsnd_reg {
RSND_REG_SHARE26, RSND_REG_SHARE26,
RSND_REG_SHARE27, RSND_REG_SHARE27,
RSND_REG_SHARE28, RSND_REG_SHARE28,
RSND_REG_SHARE29,
RSND_REG_MAX, RSND_REG_MAX,
}; };
@ -119,7 +132,7 @@ enum rsnd_reg {
#define RSND_REG_SSI_CTRL RSND_REG_SHARE02 #define RSND_REG_SSI_CTRL RSND_REG_SHARE02
#define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03 #define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03
#define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04 #define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04
#define RSND_REG_INT_ENABLE RSND_REG_SHARE05 #define RSND_REG_SSI_INT_ENABLE RSND_REG_SHARE05
#define RSND_REG_SRC_BSDSR RSND_REG_SHARE06 #define RSND_REG_SRC_BSDSR RSND_REG_SHARE06
#define RSND_REG_SRC_BSISR RSND_REG_SHARE07 #define RSND_REG_SRC_BSISR RSND_REG_SHARE07
#define RSND_REG_DIV_EN RSND_REG_SHARE08 #define RSND_REG_DIV_EN RSND_REG_SHARE08
@ -136,13 +149,14 @@ enum rsnd_reg {
#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19
#define RSND_REG_CMD_CTRL RSND_REG_SHARE20 #define RSND_REG_CMD_CTRL RSND_REG_SHARE20
#define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21
#define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22 #define RSND_REG_SSI_BUSIF_DALIGN RSND_REG_SHARE22
#define RSND_REG_DVC_VRCTR RSND_REG_SHARE23 #define RSND_REG_DVC_VRCTR RSND_REG_SHARE23
#define RSND_REG_DVC_VRPDR RSND_REG_SHARE24 #define RSND_REG_DVC_VRPDR RSND_REG_SHARE24
#define RSND_REG_DVC_VRDBR RSND_REG_SHARE25 #define RSND_REG_DVC_VRDBR RSND_REG_SHARE25
#define RSND_REG_SCU_SYS_STATUS1 RSND_REG_SHARE26 #define RSND_REG_SCU_SYS_STATUS1 RSND_REG_SHARE26
#define RSND_REG_SCU_SYS_INT_EN1 RSND_REG_SHARE27 #define RSND_REG_SCU_SYS_INT_EN1 RSND_REG_SHARE27
#define RSND_REG_SRC_INT_ENABLE0 RSND_REG_SHARE28 #define RSND_REG_SRC_INT_ENABLE0 RSND_REG_SHARE28
#define RSND_REG_SRC_BUSIF_DALIGN RSND_REG_SHARE29
struct rsnd_of_data; struct rsnd_of_data;
struct rsnd_priv; struct rsnd_priv;
@ -157,27 +171,28 @@ struct rsnd_dai_stream;
rsnd_read(rsnd_mod_to_priv(m), m, RSND_REG_##r) rsnd_read(rsnd_mod_to_priv(m), m, RSND_REG_##r)
#define rsnd_mod_write(m, r, d) \ #define rsnd_mod_write(m, r, d) \
rsnd_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d) rsnd_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d)
#define rsnd_mod_force_write(m, r, d) \
rsnd_force_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d)
#define rsnd_mod_bset(m, r, s, d) \ #define rsnd_mod_bset(m, r, s, d) \
rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d) rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d)
u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg);
void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod, void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
enum rsnd_reg reg, u32 data); enum rsnd_reg reg, u32 data);
void rsnd_force_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
enum rsnd_reg reg, u32 data);
void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
u32 mask, u32 data); u32 mask, u32 data);
u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io); u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
void rsnd_path_parse(struct rsnd_priv *priv,
struct rsnd_dai_stream *io);
/* /*
* R-Car DMA * R-Car DMA
*/ */
struct rsnd_dma; struct rsnd_dma;
struct rsnd_dma_ops {
void (*start)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
void (*stop)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
int (*init)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id,
struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
void (*quit)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
};
struct rsnd_dmaen { struct rsnd_dmaen {
struct dma_chan *chan; struct dma_chan *chan;
@ -217,6 +232,8 @@ struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
*/ */
enum rsnd_mod_type { enum rsnd_mod_type {
RSND_MOD_DVC = 0, RSND_MOD_DVC = 0,
RSND_MOD_MIX,
RSND_MOD_CTU,
RSND_MOD_SRC, RSND_MOD_SRC,
RSND_MOD_SSI, RSND_MOD_SSI,
RSND_MOD_MAX, RSND_MOD_MAX,
@ -312,7 +329,7 @@ struct rsnd_mod {
#define rsnd_mod_to_priv(mod) ((mod)->priv) #define rsnd_mod_to_priv(mod) ((mod)->priv)
#define rsnd_mod_to_dma(mod) (&(mod)->dma) #define rsnd_mod_to_dma(mod) (&(mod)->dma)
#define rsnd_mod_id(mod) ((mod)->id) #define rsnd_mod_id(mod) ((mod) ? (mod)->id : -1)
#define rsnd_mod_hw_start(mod) clk_enable((mod)->clk) #define rsnd_mod_hw_start(mod) clk_enable((mod)->clk)
#define rsnd_mod_hw_stop(mod) clk_disable((mod)->clk) #define rsnd_mod_hw_stop(mod) clk_disable((mod)->clk)
@ -345,9 +362,12 @@ struct rsnd_dai_stream {
int byte_per_period; int byte_per_period;
int next_period_byte; int next_period_byte;
}; };
#define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) #define rsnd_io_to_mod(io, i) ((i) < RSND_MOD_MAX ? (io)->mod[(i)] : NULL)
#define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) #define rsnd_io_to_mod_ssi(io) rsnd_io_to_mod((io), RSND_MOD_SSI)
#define rsnd_io_to_mod_dvc(io) ((io)->mod[RSND_MOD_DVC]) #define rsnd_io_to_mod_src(io) rsnd_io_to_mod((io), RSND_MOD_SRC)
#define rsnd_io_to_mod_ctu(io) rsnd_io_to_mod((io), RSND_MOD_CTU)
#define rsnd_io_to_mod_mix(io) rsnd_io_to_mod((io), RSND_MOD_MIX)
#define rsnd_io_to_mod_dvc(io) rsnd_io_to_mod((io), RSND_MOD_DVC)
#define rsnd_io_to_rdai(io) ((io)->rdai) #define rsnd_io_to_rdai(io) ((io)->rdai)
#define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io))) #define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io)))
#define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io) #define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io)
@ -436,12 +456,6 @@ struct rsnd_priv {
*/ */
void *gen; void *gen;
/*
* below value will be filled on rsnd_src_probe()
*/
void *src;
int src_nr;
/* /*
* below value will be filled on rsnd_adg_probe() * below value will be filled on rsnd_adg_probe()
*/ */
@ -458,6 +472,24 @@ struct rsnd_priv {
void *ssi; void *ssi;
int ssi_nr; int ssi_nr;
/*
* below value will be filled on rsnd_src_probe()
*/
void *src;
int src_nr;
/*
* below value will be filled on rsnd_ctu_probe()
*/
void *ctu;
int ctu_nr;
/*
* below value will be filled on rsnd_mix_probe()
*/
void *mix;
int mix_nr;
/* /*
* below value will be filled on rsnd_dvc_probe() * below value will be filled on rsnd_dvc_probe()
*/ */
@ -530,6 +562,19 @@ int rsnd_kctrl_new_e(struct rsnd_mod *mod,
const char * const *texts, const char * const *texts,
u32 max); u32 max);
/*
* R-Car SSI
*/
int rsnd_ssi_probe(struct platform_device *pdev,
const struct rsnd_of_data *of_data,
struct rsnd_priv *priv);
void rsnd_ssi_remove(struct platform_device *pdev,
struct rsnd_priv *priv);
struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod);
int rsnd_ssi_use_busif(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
/* /*
* R-Car SRC * R-Car SRC
*/ */
@ -550,20 +595,27 @@ int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod,
int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod); int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod);
int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod); int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod);
#define rsnd_src_nr(priv) ((priv)->src_nr)
/* /*
* R-Car SSI * R-Car CTU
*/ */
int rsnd_ssi_probe(struct platform_device *pdev, int rsnd_ctu_probe(struct platform_device *pdev,
const struct rsnd_of_data *of_data, const struct rsnd_of_data *of_data,
struct rsnd_priv *priv); struct rsnd_priv *priv);
void rsnd_ssi_remove(struct platform_device *pdev,
void rsnd_ctu_remove(struct platform_device *pdev,
struct rsnd_priv *priv); struct rsnd_priv *priv);
struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id);
int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); /*
int rsnd_ssi_use_busif(struct rsnd_dai_stream *io, struct rsnd_mod *mod); * R-Car MIX
*/
int rsnd_mix_probe(struct platform_device *pdev,
const struct rsnd_of_data *of_data,
struct rsnd_priv *priv);
void rsnd_mix_remove(struct platform_device *pdev,
struct rsnd_priv *priv);
struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id);
/* /*
* R-Car DVC * R-Car DVC
@ -575,7 +627,4 @@ void rsnd_dvc_remove(struct platform_device *pdev,
struct rsnd_priv *priv); struct rsnd_priv *priv);
struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id);
#define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
#endif #endif

View File

@ -41,6 +41,7 @@ static const struct rsrc_card_of_data routes_of_ssi0_ak4642 = {
static const struct of_device_id rsrc_card_of_match[] = { static const struct of_device_id rsrc_card_of_match[] = {
{ .compatible = "renesas,rsrc-card,lager", .data = &routes_of_ssi0_ak4642 }, { .compatible = "renesas,rsrc-card,lager", .data = &routes_of_ssi0_ak4642 },
{ .compatible = "renesas,rsrc-card,koelsch", .data = &routes_of_ssi0_ak4642 }, { .compatible = "renesas,rsrc-card,koelsch", .data = &routes_of_ssi0_ak4642 },
{ .compatible = "renesas,rsrc-card", },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, rsrc_card_of_match); MODULE_DEVICE_TABLE(of, rsrc_card_of_match);
@ -242,8 +243,15 @@ static int rsrc_card_parse_links(struct device_node *np,
snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name); snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name);
/* additional name prefix */ /* additional name prefix */
priv->codec_conf.of_node = dai_link->codec_of_node; if (of_data) {
priv->codec_conf.name_prefix = of_data->prefix; priv->codec_conf.of_node = dai_link->codec_of_node;
priv->codec_conf.name_prefix = of_data->prefix;
} else {
snd_soc_of_parse_audio_prefix(&priv->snd_card,
&priv->codec_conf,
dai_link->codec_of_node,
"audio-prefix");
}
/* set dai_name */ /* set dai_name */
snprintf(dai_props->dai_name, DAI_NAME_NUM, "be.%s", snprintf(dai_props->dai_name, DAI_NAME_NUM, "be.%s",
@ -361,8 +369,14 @@ static int rsrc_card_parse_of(struct device_node *node,
priv->snd_card.num_links = num; priv->snd_card.num_links = num;
priv->snd_card.codec_conf = &priv->codec_conf; priv->snd_card.codec_conf = &priv->codec_conf;
priv->snd_card.num_configs = 1; priv->snd_card.num_configs = 1;
priv->snd_card.of_dapm_routes = of_data->routes;
priv->snd_card.num_of_dapm_routes = of_data->num_routes; if (of_data) {
priv->snd_card.of_dapm_routes = of_data->routes;
priv->snd_card.num_of_dapm_routes = of_data->num_routes;
} else {
snd_soc_of_parse_audio_routing(&priv->snd_card,
"audio-routing");
}
/* Parse the card name from DT */ /* Parse the card name from DT */
snd_soc_of_parse_card_name(&priv->snd_card, "card-name"); snd_soc_of_parse_card_name(&priv->snd_card, "card-name");

View File

@ -30,6 +30,7 @@ struct rsnd_src {
#define RSND_SRC_NAME_SIZE 16 #define RSND_SRC_NAME_SIZE 16
#define rsnd_src_nr(priv) ((priv)->src_nr)
#define rsnd_enable_sync_convert(src) ((src)->sen.val) #define rsnd_enable_sync_convert(src) ((src)->sen.val)
#define rsnd_src_of_node(priv) \ #define rsnd_src_of_node(priv) \
of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src") of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src")
@ -117,6 +118,20 @@ struct rsnd_src {
/* /*
* Gen1/Gen2 common functions * Gen1/Gen2 common functions
*/ */
static void rsnd_src_soft_reset(struct rsnd_mod *mod)
{
rsnd_mod_write(mod, SRC_SWRSR, 0);
rsnd_mod_write(mod, SRC_SWRSR, 1);
}
#define rsnd_src_initialize_lock(mod) __rsnd_src_initialize_lock(mod, 1)
#define rsnd_src_initialize_unlock(mod) __rsnd_src_initialize_lock(mod, 0)
static void __rsnd_src_initialize_lock(struct rsnd_mod *mod, u32 enable)
{
rsnd_mod_write(mod, SRC_SRCIR, enable);
}
static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io, static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
struct rsnd_mod *mod) struct rsnd_mod *mod)
{ {
@ -133,7 +148,6 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
int use_busif) int use_busif)
{ {
struct rsnd_dai *rdai = rsnd_io_to_rdai(io); struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
int ssi_id = rsnd_mod_id(ssi_mod); int ssi_id = rsnd_mod_id(ssi_mod);
/* /*
@ -170,27 +184,14 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
* DMA settings for SSIU * DMA settings for SSIU
*/ */
if (use_busif) { if (use_busif) {
u32 val = 0x76543210; u32 val = rsnd_get_dalign(ssi_mod, io);
u32 mask = ~0;
rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR,
rsnd_get_adinr(ssi_mod, io)); rsnd_get_adinr_bit(ssi_mod, io));
rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1);
rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1);
mask <<= runtime->channels * 4; rsnd_mod_write(ssi_mod, SSI_BUSIF_DALIGN, val);
val = val & mask;
switch (runtime->sample_bits) {
case 16:
val |= 0x67452301 & ~mask;
break;
case 32:
val |= 0x76543210 & ~mask;
break;
}
rsnd_mod_write(ssi_mod, BUSIF_DALIGN, val);
} }
return 0; return 0;
@ -215,10 +216,9 @@ int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod)
return 0; return 0;
/* enable SSI interrupt if Gen2 */ /* enable SSI interrupt if Gen2 */
if (rsnd_ssi_is_dma_mode(ssi_mod)) rsnd_mod_write(ssi_mod, SSI_INT_ENABLE,
rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0e000000); rsnd_ssi_is_dma_mode(ssi_mod) ?
else 0x0e000000 : 0x0f000000);
rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000);
return 0; return 0;
} }
@ -231,7 +231,7 @@ int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod)
return 0; return 0;
/* disable SSI interrupt if Gen2 */ /* disable SSI interrupt if Gen2 */
rsnd_mod_write(ssi_mod, INT_ENABLE, 0x00000000); rsnd_mod_write(ssi_mod, SSI_INT_ENABLE, 0x00000000);
return 0; return 0;
} }
@ -294,12 +294,8 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod,
if (convert_rate) if (convert_rate)
fsrate = 0x0400000 / convert_rate * runtime->rate; fsrate = 0x0400000 / convert_rate * runtime->rate;
/* set/clear soft reset */
rsnd_mod_write(mod, SRC_SWRSR, 0);
rsnd_mod_write(mod, SRC_SWRSR, 1);
/* Set channel number and output bit length */ /* Set channel number and output bit length */
rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod, io)); rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr_bit(mod, io));
/* Enable the initial value of IFS */ /* Enable the initial value of IFS */
if (fsrate) { if (fsrate) {
@ -358,17 +354,15 @@ static int rsnd_src_init(struct rsnd_mod *mod,
rsnd_mod_hw_start(mod); rsnd_mod_hw_start(mod);
rsnd_src_soft_reset(mod);
rsnd_src_initialize_lock(mod);
src->err = 0; src->err = 0;
/* reset sync convert_rate */ /* reset sync convert_rate */
src->sync.val = 0; src->sync.val = 0;
/*
* Initialize the operation of the SRC internal circuits
* see rsnd_src_start()
*/
rsnd_mod_write(mod, SRC_SRCIR, 1);
return 0; return 0;
} }
@ -395,11 +389,7 @@ static int rsnd_src_quit(struct rsnd_mod *mod,
static int rsnd_src_start(struct rsnd_mod *mod) static int rsnd_src_start(struct rsnd_mod *mod)
{ {
/* rsnd_src_initialize_unlock(mod);
* Cancel the initialization and operate the SRC function
* see rsnd_src_init()
*/
rsnd_mod_write(mod, SRC_SRCIR, 0);
return 0; return 0;
} }
@ -617,6 +607,14 @@ static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable)
int_val = 0; int_val = 0;
} }
/*
* WORKAROUND
*
* ignore over flow error when rsnd_enable_sync_convert()
*/
if (rsnd_enable_sync_convert(src))
sys_int_val = sys_int_val & 0xffff;
rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val); rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val); rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val); rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
@ -632,11 +630,22 @@ static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod)
static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod) static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod)
{ {
u32 val = OUF_SRC(rsnd_mod_id(mod)); struct rsnd_src *src = rsnd_mod_to_src(mod);
u32 val0, val1;
bool ret = false; bool ret = false;
if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val) || val0 = val1 = OUF_SRC(rsnd_mod_id(mod));
(rsnd_mod_read(mod, SCU_SYS_STATUS1) & val)) {
/*
* WORKAROUND
*
* ignore over flow error when rsnd_enable_sync_convert()
*/
if (rsnd_enable_sync_convert(src))
val0 = val0 & 0xffff;
if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val0) ||
(rsnd_mod_read(mod, SCU_SYS_STATUS1) & val1)) {
struct rsnd_src *src = rsnd_mod_to_src(mod); struct rsnd_src *src = rsnd_mod_to_src(mod);
src->err++; src->err++;
@ -652,7 +661,20 @@ static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod)
static int _rsnd_src_start_gen2(struct rsnd_mod *mod, static int _rsnd_src_start_gen2(struct rsnd_mod *mod,
struct rsnd_dai_stream *io) struct rsnd_dai_stream *io)
{ {
u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11; struct rsnd_src *src = rsnd_mod_to_src(mod);
u32 val;
val = rsnd_get_dalign(mod, io);
rsnd_mod_write(mod, SRC_BUSIF_DALIGN, val);
/*
* WORKAROUND
*
* Enable SRC output if you want to use sync convert together with DVC
*/
val = (rsnd_io_to_mod_dvc(io) && !rsnd_enable_sync_convert(src)) ?
0x01 : 0x11;
rsnd_mod_write(mod, SRC_CTRL, val); rsnd_mod_write(mod, SRC_CTRL, val);
@ -921,13 +943,6 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod,
if (!rsnd_rdai_is_clk_master(rdai)) if (!rsnd_rdai_is_clk_master(rdai))
return 0; return 0;
/*
* We can't use SRC sync convert
* if it has DVC
*/
if (rsnd_io_to_mod_dvc(io))
return 0;
/* /*
* enable sync convert * enable sync convert
*/ */
@ -1047,10 +1062,8 @@ int rsnd_src_probe(struct platform_device *pdev,
return 0; return 0;
src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL);
if (!src) { if (!src)
dev_err(dev, "SRC allocate failed\n");
return -ENOMEM; return -ENOMEM;
}
priv->src_nr = nr; priv->src_nr = nr;
priv->src = src; priv->src = src;

View File

@ -770,10 +770,8 @@ int rsnd_ssi_probe(struct platform_device *pdev,
*/ */
nr = info->ssi_info_nr; nr = info->ssi_info_nr;
ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL); ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL);
if (!ssi) { if (!ssi)
dev_err(dev, "SSI allocate failed\n");
return -ENOMEM; return -ENOMEM;
}
priv->ssi = ssi; priv->ssi = ssi;
priv->ssi_nr = nr; priv->ssi_nr = nr;