Loading drivers/soundwire/soundwire.c +37 −0 Original line number Diff line number Diff line Loading @@ -239,6 +239,43 @@ void swr_port_response(struct swr_master *mstr, u8 tid) } EXPORT_SYMBOL(swr_port_response); /** * swr_slvdev_datapath_control - Enables/Disables soundwire slave device * data path * @dev: pointer to soundwire slave device * @dev_num: device number of the soundwire slave device * * Returns error code for failure and 0 for success */ int swr_slvdev_datapath_control(struct swr_device *dev, u8 dev_num, bool enable) { struct swr_master *master; if (!dev) return -ENODEV; master = dev->master; if (!master) return -EINVAL; if (dev->group_id) { /* Broadcast */ if (master->gr_sid != dev_num) { if (!master->gr_sid) master->gr_sid = dev_num; else return 0; } } if (master->slvdev_datapath_control) master->slvdev_datapath_control(master, enable); return 0; } EXPORT_SYMBOL(swr_slvdev_datapath_control); /** * swr_connect_port - enable soundwire slave port(s) * @dev: pointer to soundwire slave device Loading drivers/soundwire/swr-wcd-ctrl.c +58 −14 Original line number Diff line number Diff line Loading @@ -601,6 +601,62 @@ static struct swr_port_info *swrm_get_port(struct swr_master *master, return port; } static void swrm_slvdev_datapath_control(struct swr_master *master, bool enable) { u8 bank; u32 value, n_col; struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master); int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK | SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK | SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK); int col_mask = SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK; u8 active_bank; bank = get_inactive_bank_num(swrm); dev_dbg(swrm->dev, "%s: enable: %d, slvdev_dp_enable_cnt: %d\n", __func__, enable, swrm->slvdev_dp_enable_cnt); if (enable) { swrm->slvdev_dp_enable_cnt++; active_bank = bank ? 0 : 1; value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(active_bank)); if (((value & col_mask) >> SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) == SWR_MAX_COL) return; /* set Row = 48 and col = 16 */ n_col = SWR_MAX_COL; } else { /* * Do not change to 48x2 if number of channels configured * as stereo and if disable datapath is called for the * first slave device */ swrm->slvdev_dp_enable_cnt--; if (swrm->slvdev_dp_enable_cnt > 0) return; /* set Row = 48 and col = 2 */ n_col = SWR_MIN_COL; } value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank)); value &= (~mask); value |= ((0 << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | (n_col << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); swrm->write(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); enable_bank_switch(swrm, bank, SWR_MAX_ROW, n_col); } static void swrm_apply_port_config(struct swr_master *master) { u32 value; Loading @@ -615,10 +671,6 @@ static void swrm_apply_port_config(struct swr_master *master) u32 val[SWRM_MAX_PORT_REG]; int len = 0; int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK | SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK | SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK); if (!swrm) { pr_err("%s: Invalid handle to swr controller\n", __func__); Loading @@ -629,15 +681,6 @@ static void swrm_apply_port_config(struct swr_master *master) dev_dbg(swrm->dev, "%s: enter bank: %d master_ports: %d\n", __func__, bank, master->num_port); /* set Row = 48 and col = 16 */ value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank)); value &= (~mask); value |= ((0 << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | (7 << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); swrm->write(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); swrm_cmd_fifo_wr_cmd(swrm, 0x01, 0xF, 0x00, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(bank)); Loading Loading @@ -703,7 +746,6 @@ static void swrm_apply_port_config(struct swr_master *master) } } swrm->bulk_write(swrm->handle, reg, val, len); enable_bank_switch(swrm, bank, SWR_MAX_ROW, SWR_MAX_COL); } static int swrm_connect_port(struct swr_master *master, Loading Loading @@ -1057,6 +1099,7 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm) u32 value[SWRM_MAX_INIT_REG]; int len = 0; swrm->slvdev_dp_enable_cnt = 0; /* Clear Rows and Cols */ val = ((row_ctrl << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | (col_ctrl << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | Loading Loading @@ -1174,6 +1217,7 @@ static int swrm_probe(struct platform_device *pdev) swrm->master.get_logical_dev_num = swrm_get_logical_dev_num; swrm->master.connect_port = swrm_connect_port; swrm->master.disconnect_port = swrm_disconnect_port; swrm->master.slvdev_datapath_control = swrm_slvdev_datapath_control; swrm->master.dev.parent = &pdev->dev; swrm->master.dev.of_node = pdev->dev.of_node; swrm->master.num_port = 0; Loading drivers/soundwire/swr-wcd-ctrl.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -96,6 +96,7 @@ struct swr_mstr_ctrl { struct platform_device *pdev; int num_rx_chs; u8 num_cfg_devs; u8 slvdev_dp_enable_cnt; }; #endif /* _SWR_WCD_CTRL_H */ include/linux/soundwire/soundwire.h +4 −1 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -151,6 +151,7 @@ struct swr_master { const void *buf, size_t len); int (*get_logical_dev_num)(struct swr_master *mstr, u64 dev_id, u8 *dev_num); void (*slvdev_datapath_control)(struct swr_master *mstr, bool enable); }; static inline struct swr_master *to_swr_master(struct device *dev) Loading Loading @@ -304,4 +305,6 @@ extern int swr_device_down(struct swr_device *swr_dev); extern int swr_reset_device(struct swr_device *swr_dev); extern int swr_slvdev_datapath_control(struct swr_device *swr_dev, u8 dev_num, bool enable); #endif /* _LINUX_SOUNDWIRE_H */ sound/soc/codecs/wsa881x.c +7 −1 Original line number Diff line number Diff line /* * Copyright (c) 2015, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -740,6 +740,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w, wsa881x_boost_ctrl(codec, ENABLE); break; case SND_SOC_DAPM_POST_PMD: swr_slvdev_datapath_control(wsa881x->swr_slave, wsa881x->swr_slave->dev_num, false); if (wsa881x->boost_enable) wsa881x_boost_ctrl(codec, DISABLE); wsa881x_resource_acquire(codec, DISABLE); Loading Loading @@ -805,6 +808,9 @@ static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w, regmap_multi_reg_write(wsa881x->regmap, wsa881x_pre_pmu_pa, ARRAY_SIZE(wsa881x_pre_pmu_pa)); swr_slvdev_datapath_control(wsa881x->swr_slave, wsa881x->swr_slave->dev_num, true); break; case SND_SOC_DAPM_POST_PMU: if (WSA881X_IS_2_0(wsa881x->version)) { Loading Loading
drivers/soundwire/soundwire.c +37 −0 Original line number Diff line number Diff line Loading @@ -239,6 +239,43 @@ void swr_port_response(struct swr_master *mstr, u8 tid) } EXPORT_SYMBOL(swr_port_response); /** * swr_slvdev_datapath_control - Enables/Disables soundwire slave device * data path * @dev: pointer to soundwire slave device * @dev_num: device number of the soundwire slave device * * Returns error code for failure and 0 for success */ int swr_slvdev_datapath_control(struct swr_device *dev, u8 dev_num, bool enable) { struct swr_master *master; if (!dev) return -ENODEV; master = dev->master; if (!master) return -EINVAL; if (dev->group_id) { /* Broadcast */ if (master->gr_sid != dev_num) { if (!master->gr_sid) master->gr_sid = dev_num; else return 0; } } if (master->slvdev_datapath_control) master->slvdev_datapath_control(master, enable); return 0; } EXPORT_SYMBOL(swr_slvdev_datapath_control); /** * swr_connect_port - enable soundwire slave port(s) * @dev: pointer to soundwire slave device Loading
drivers/soundwire/swr-wcd-ctrl.c +58 −14 Original line number Diff line number Diff line Loading @@ -601,6 +601,62 @@ static struct swr_port_info *swrm_get_port(struct swr_master *master, return port; } static void swrm_slvdev_datapath_control(struct swr_master *master, bool enable) { u8 bank; u32 value, n_col; struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master); int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK | SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK | SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK); int col_mask = SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK; u8 active_bank; bank = get_inactive_bank_num(swrm); dev_dbg(swrm->dev, "%s: enable: %d, slvdev_dp_enable_cnt: %d\n", __func__, enable, swrm->slvdev_dp_enable_cnt); if (enable) { swrm->slvdev_dp_enable_cnt++; active_bank = bank ? 0 : 1; value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(active_bank)); if (((value & col_mask) >> SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) == SWR_MAX_COL) return; /* set Row = 48 and col = 16 */ n_col = SWR_MAX_COL; } else { /* * Do not change to 48x2 if number of channels configured * as stereo and if disable datapath is called for the * first slave device */ swrm->slvdev_dp_enable_cnt--; if (swrm->slvdev_dp_enable_cnt > 0) return; /* set Row = 48 and col = 2 */ n_col = SWR_MIN_COL; } value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank)); value &= (~mask); value |= ((0 << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | (n_col << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); swrm->write(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); enable_bank_switch(swrm, bank, SWR_MAX_ROW, n_col); } static void swrm_apply_port_config(struct swr_master *master) { u32 value; Loading @@ -615,10 +671,6 @@ static void swrm_apply_port_config(struct swr_master *master) u32 val[SWRM_MAX_PORT_REG]; int len = 0; int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK | SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK | SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK); if (!swrm) { pr_err("%s: Invalid handle to swr controller\n", __func__); Loading @@ -629,15 +681,6 @@ static void swrm_apply_port_config(struct swr_master *master) dev_dbg(swrm->dev, "%s: enter bank: %d master_ports: %d\n", __func__, bank, master->num_port); /* set Row = 48 and col = 16 */ value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank)); value &= (~mask); value |= ((0 << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | (7 << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); swrm->write(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); swrm_cmd_fifo_wr_cmd(swrm, 0x01, 0xF, 0x00, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(bank)); Loading Loading @@ -703,7 +746,6 @@ static void swrm_apply_port_config(struct swr_master *master) } } swrm->bulk_write(swrm->handle, reg, val, len); enable_bank_switch(swrm, bank, SWR_MAX_ROW, SWR_MAX_COL); } static int swrm_connect_port(struct swr_master *master, Loading Loading @@ -1057,6 +1099,7 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm) u32 value[SWRM_MAX_INIT_REG]; int len = 0; swrm->slvdev_dp_enable_cnt = 0; /* Clear Rows and Cols */ val = ((row_ctrl << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | (col_ctrl << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | Loading Loading @@ -1174,6 +1217,7 @@ static int swrm_probe(struct platform_device *pdev) swrm->master.get_logical_dev_num = swrm_get_logical_dev_num; swrm->master.connect_port = swrm_connect_port; swrm->master.disconnect_port = swrm_disconnect_port; swrm->master.slvdev_datapath_control = swrm_slvdev_datapath_control; swrm->master.dev.parent = &pdev->dev; swrm->master.dev.of_node = pdev->dev.of_node; swrm->master.num_port = 0; Loading
drivers/soundwire/swr-wcd-ctrl.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -96,6 +96,7 @@ struct swr_mstr_ctrl { struct platform_device *pdev; int num_rx_chs; u8 num_cfg_devs; u8 slvdev_dp_enable_cnt; }; #endif /* _SWR_WCD_CTRL_H */
include/linux/soundwire/soundwire.h +4 −1 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -151,6 +151,7 @@ struct swr_master { const void *buf, size_t len); int (*get_logical_dev_num)(struct swr_master *mstr, u64 dev_id, u8 *dev_num); void (*slvdev_datapath_control)(struct swr_master *mstr, bool enable); }; static inline struct swr_master *to_swr_master(struct device *dev) Loading Loading @@ -304,4 +305,6 @@ extern int swr_device_down(struct swr_device *swr_dev); extern int swr_reset_device(struct swr_device *swr_dev); extern int swr_slvdev_datapath_control(struct swr_device *swr_dev, u8 dev_num, bool enable); #endif /* _LINUX_SOUNDWIRE_H */
sound/soc/codecs/wsa881x.c +7 −1 Original line number Diff line number Diff line /* * Copyright (c) 2015, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -740,6 +740,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w, wsa881x_boost_ctrl(codec, ENABLE); break; case SND_SOC_DAPM_POST_PMD: swr_slvdev_datapath_control(wsa881x->swr_slave, wsa881x->swr_slave->dev_num, false); if (wsa881x->boost_enable) wsa881x_boost_ctrl(codec, DISABLE); wsa881x_resource_acquire(codec, DISABLE); Loading Loading @@ -805,6 +808,9 @@ static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w, regmap_multi_reg_write(wsa881x->regmap, wsa881x_pre_pmu_pa, ARRAY_SIZE(wsa881x_pre_pmu_pa)); swr_slvdev_datapath_control(wsa881x->swr_slave, wsa881x->swr_slave->dev_num, true); break; case SND_SOC_DAPM_POST_PMU: if (WSA881X_IS_2_0(wsa881x->version)) { Loading