From 420c0117db25db38b72b6230223f7a976d3070ea Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 17 Jun 2018 19:02:04 +0200 Subject: dmaengine: pxa: use a dma slave map In order to remove the specific knowledge of the dma mapping from PXA drivers, add a default slave map for pxa architectures. This won't impact MMP architecture, but is aimed only at all PXA boards. This is the first step, and once all drivers are converted, pxad_filter_fn() will be made static, and the DMA resources removed from device.c. Signed-off-by: Robert Jarzmik Reported-by: Arnd Bergmann Acked-by: Vinod Koul --- drivers/dma/pxa_dma.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index b53fb618bbf6..9505334f9c6e 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -179,6 +179,8 @@ static unsigned int pxad_drcmr(unsigned int line) return 0x1000 + line * 4; } +bool pxad_filter_fn(struct dma_chan *chan, void *param); + /* * Debug fs */ @@ -1396,9 +1398,10 @@ static int pxad_probe(struct platform_device *op) { struct pxad_device *pdev; const struct of_device_id *of_id; + const struct dma_slave_map *slave_map = NULL; struct mmp_dma_platdata *pdata = dev_get_platdata(&op->dev); struct resource *iores; - int ret, dma_channels = 0, nb_requestors = 0; + int ret, dma_channels = 0, nb_requestors = 0, slave_map_cnt = 0; const enum dma_slave_buswidth widths = DMA_SLAVE_BUSWIDTH_1_BYTE | DMA_SLAVE_BUSWIDTH_2_BYTES | DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -1429,6 +1432,8 @@ static int pxad_probe(struct platform_device *op) } else if (pdata && pdata->dma_channels) { dma_channels = pdata->dma_channels; nb_requestors = pdata->nb_requestors; + slave_map = pdata->slave_map; + slave_map_cnt = pdata->slave_map_cnt; } else { dma_channels = 32; /* default 32 channel */ } @@ -1440,6 +1445,9 @@ static int pxad_probe(struct platform_device *op) pdev->slave.device_prep_dma_memcpy = pxad_prep_memcpy; pdev->slave.device_prep_slave_sg = pxad_prep_slave_sg; pdev->slave.device_prep_dma_cyclic = pxad_prep_dma_cyclic; + pdev->slave.filter.map = slave_map; + pdev->slave.filter.mapcnt = slave_map_cnt; + pdev->slave.filter.fn = pxad_filter_fn; pdev->slave.copy_align = PDMA_ALIGNMENT; pdev->slave.src_addr_widths = widths; -- cgit v1.2.3 From 88a0513cf6114bbabbd3a158f039dbd03f49e0bf Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 17 Jun 2018 19:02:06 +0200 Subject: dmaengine: pxa: add a default requestor policy As what former drcmr -1 value meant, add a this as a default to each channel, ie. that by default no requestor line is used. This is specifically used for network drivers smc91x and smc911x, and needed for their port to slave maps. Cc: Arnd Bergmann Signed-off-by: Robert Jarzmik Acked-by: Vinod Koul --- drivers/dma/pxa_dma.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index 9505334f9c6e..b31c28b67ad3 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -762,6 +762,8 @@ static void pxad_free_chan_resources(struct dma_chan *dchan) dma_pool_destroy(chan->desc_pool); chan->desc_pool = NULL; + chan->drcmr = U32_MAX; + chan->prio = PXAD_PRIO_LOWEST; } static void pxad_free_desc(struct virt_dma_desc *vd) @@ -1386,6 +1388,9 @@ static int pxad_init_dmadev(struct platform_device *op, c = devm_kzalloc(&op->dev, sizeof(*c), GFP_KERNEL); if (!c) return -ENOMEM; + + c->drcmr = U32_MAX; + c->prio = PXAD_PRIO_LOWEST; c->vc.desc_free = pxad_free_desc; vchan_init(&c->vc, &pdev->slave); init_waitqueue_head(&c->wq_state); -- cgit v1.2.3 From 6b3348f9e6eb35d2c2d49ffa274039ef9a901adc Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 17 Jun 2018 19:02:07 +0200 Subject: mmc: pxamci: remove the dmaengine compat need As the pxa architecture switched towards the dmaengine slave map, the old compatibility mechanism to acquire the dma requestor line number and priority are not needed anymore. This patch simplifies the dma resource acquisition, using the more generic function dma_request_slave_channel(). Signed-off-by: Robert Jarzmik Acked-by: Ulf Hansson --- drivers/mmc/host/pxamci.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index c763b404510f..6c94474e36f4 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -637,10 +636,8 @@ static int pxamci_probe(struct platform_device *pdev) { struct mmc_host *mmc; struct pxamci_host *host = NULL; - struct resource *r, *dmarx, *dmatx; - struct pxad_param param_rx, param_tx; + struct resource *r; int ret, irq, gpio_cd = -1, gpio_ro = -1, gpio_power = -1; - dma_cap_mask_t mask; ret = pxamci_of_init(pdev); if (ret) @@ -739,34 +736,14 @@ static int pxamci_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mmc); - if (!pdev->dev.of_node) { - dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0); - dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!dmarx || !dmatx) { - ret = -ENXIO; - goto out; - } - param_rx.prio = PXAD_PRIO_LOWEST; - param_rx.drcmr = dmarx->start; - param_tx.prio = PXAD_PRIO_LOWEST; - param_tx.drcmr = dmatx->start; - } - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - - host->dma_chan_rx = - dma_request_slave_channel_compat(mask, pxad_filter_fn, - ¶m_rx, &pdev->dev, "rx"); + host->dma_chan_rx = dma_request_slave_channel(&pdev->dev, "rx"); if (host->dma_chan_rx == NULL) { dev_err(&pdev->dev, "unable to request rx dma channel\n"); ret = -ENODEV; goto out; } - host->dma_chan_tx = - dma_request_slave_channel_compat(mask, pxad_filter_fn, - ¶m_tx, &pdev->dev, "tx"); + host->dma_chan_tx = dma_request_slave_channel(&pdev->dev, "tx"); if (host->dma_chan_tx == NULL) { dev_err(&pdev->dev, "unable to request tx dma channel\n"); ret = -ENODEV; -- cgit v1.2.3 From f727b6cda449184188d8a64987f194687bf01782 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 17 Jun 2018 19:02:08 +0200 Subject: media: pxa_camera: remove the dmaengine compat need As the pxa architecture switched towards the dmaengine slave map, the old compatibility mechanism to acquire the dma requestor line number and priority are not needed anymore. This patch simplifies the dma resource acquisition, using the more generic function dma_request_slave_channel(). Signed-off-by: Robert Jarzmik Acked-by: Hans Verkuil Acked-by: Mauro Carvalho Chehab --- drivers/media/platform/pxa_camera.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c index d85ffbfb7c1f..b6e9e93bde7a 100644 --- a/drivers/media/platform/pxa_camera.c +++ b/drivers/media/platform/pxa_camera.c @@ -2375,8 +2375,6 @@ static int pxa_camera_probe(struct platform_device *pdev) .src_maxburst = 8, .direction = DMA_DEV_TO_MEM, }; - dma_cap_mask_t mask; - struct pxad_param params; char clk_name[V4L2_CLK_NAME_SIZE]; int irq; int err = 0, i; @@ -2450,34 +2448,20 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev->base = base; /* request dma */ - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dma_cap_set(DMA_PRIVATE, mask); - - params.prio = 0; - params.drcmr = 68; - pcdev->dma_chans[0] = - dma_request_slave_channel_compat(mask, pxad_filter_fn, - ¶ms, &pdev->dev, "CI_Y"); + pcdev->dma_chans[0] = dma_request_slave_channel(&pdev->dev, "CI_Y"); if (!pcdev->dma_chans[0]) { dev_err(&pdev->dev, "Can't request DMA for Y\n"); return -ENODEV; } - params.drcmr = 69; - pcdev->dma_chans[1] = - dma_request_slave_channel_compat(mask, pxad_filter_fn, - ¶ms, &pdev->dev, "CI_U"); + pcdev->dma_chans[1] = dma_request_slave_channel(&pdev->dev, "CI_U"); if (!pcdev->dma_chans[1]) { dev_err(&pdev->dev, "Can't request DMA for Y\n"); err = -ENODEV; goto exit_free_dma_y; } - params.drcmr = 70; - pcdev->dma_chans[2] = - dma_request_slave_channel_compat(mask, pxad_filter_fn, - ¶ms, &pdev->dev, "CI_V"); + pcdev->dma_chans[2] = dma_request_slave_channel(&pdev->dev, "CI_V"); if (!pcdev->dma_chans[2]) { dev_err(&pdev->dev, "Can't request DMA for V\n"); err = -ENODEV; -- cgit v1.2.3 From ac75a50b6de3b092d084fdd9818707d0d5073ad6 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 17 Jun 2018 19:02:09 +0200 Subject: mtd: rawnand: marvell: remove the dmaengine compat need As the pxa architecture switched towards the dmaengine slave map, the old compatibility mechanism to acquire the dma requestor line number and priority are not needed anymore. This patch simplifies the dma resource acquisition, using the more generic function dma_request_slave_channel(). Signed-off-by: Daniel Mack Signed-off-by: Robert Jarzmik Acked-by: Miquel Raynal --- drivers/mtd/nand/raw/marvell_nand.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index ebb1d141b900..00d9f29bbdb6 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2612,8 +2612,6 @@ static int marvell_nfc_init_dma(struct marvell_nfc *nfc) dev); struct dma_slave_config config = {}; struct resource *r; - dma_cap_mask_t mask; - struct pxad_param param; int ret; if (!IS_ENABLED(CONFIG_PXA_DMA)) { @@ -2626,20 +2624,7 @@ static int marvell_nfc_init_dma(struct marvell_nfc *nfc) if (ret) return ret; - r = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!r) { - dev_err(nfc->dev, "No resource defined for data DMA\n"); - return -ENXIO; - } - - param.drcmr = r->start; - param.prio = PXAD_PRIO_LOWEST; - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - nfc->dma_chan = - dma_request_slave_channel_compat(mask, pxad_filter_fn, - ¶m, nfc->dev, - "data"); + nfc->dma_chan = dma_request_slave_channel(nfc->dev, "data"); if (!nfc->dma_chan) { dev_err(nfc->dev, "Unable to request data DMA channel\n"); -- cgit v1.2.3 From 273340e8bf86de53eef7073993352ea11c563696 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 17 Jun 2018 19:02:13 +0200 Subject: ata: pata_pxa: remove the dmaengine compat need As the pxa architecture switched towards the dmaengine slave map, the old compatibility mechanism to acquire the dma requestor line number and priority are not needed anymore. This patch simplifies the dma resource acquisition, using the more generic function dma_request_slave_channel(). Signed-off-by: Robert Jarzmik Acked-by: Bartlomiej Zolnierkiewicz --- drivers/ata/pata_pxa.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c index f6c46e9a4dc0..e8b6a2e464c9 100644 --- a/drivers/ata/pata_pxa.c +++ b/drivers/ata/pata_pxa.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -180,8 +179,6 @@ static int pxa_ata_probe(struct platform_device *pdev) struct resource *irq_res; struct pata_pxa_pdata *pdata = dev_get_platdata(&pdev->dev); struct dma_slave_config config; - dma_cap_mask_t mask; - struct pxad_param param; int ret = 0; /* @@ -278,10 +275,6 @@ static int pxa_ata_probe(struct platform_device *pdev) ap->private_data = data; - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - param.prio = PXAD_PRIO_LOWEST; - param.drcmr = pdata->dma_dreq; memset(&config, 0, sizeof(config)); config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; @@ -294,8 +287,7 @@ static int pxa_ata_probe(struct platform_device *pdev) * Request the DMA channel */ data->dma_chan = - dma_request_slave_channel_compat(mask, pxad_filter_fn, - ¶m, &pdev->dev, "data"); + dma_request_slave_channel(&pdev->dev, "data"); if (!data->dma_chan) return -EBUSY; ret = dmaengine_slave_config(data->dma_chan, &config); -- cgit v1.2.3 From 9fba738a53dda20e748d6ee240b6c017c8146b4b Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 19 Jun 2018 16:41:41 +0200 Subject: clk: add duty cycle support Add the possibility to apply and query the clock signal duty cycle ratio. This is useful when the duty cycle of the clock signal depends on some other parameters controlled by the clock framework. For example, the duty cycle of a divider may depends on the raw divider setting (ratio = N / div) , which is controlled by the CCF. In such case, going through the pwm framework to control the duty cycle ratio of this clock would be a burden. A clock provider is not required to implement the operation to set and get the duty cycle. If it does not implement .get_duty_cycle(), the ratio is assumed to be 50%. This change also adds a new flag, CLK_DUTY_CYCLE_PARENT. This flag should be used to indicate that a clock, such as gates and muxes, may inherit the duty cycle ratio of its parent clock. If a clock does not provide a get_duty_cycle() callback and has CLK_DUTY_CYCLE_PARENT, then the call will be directly forwarded to its parent clock, if any. For set_duty_cycle(), the clock should also have CLK_SET_RATE_PARENT for the call to be forwarded Signed-off-by: Jerome Brunet Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20180619144141.8506-1-jbrunet@baylibre.com --- drivers/clk/clk.c | 199 +++++++++++++++++++++++++++++++++++++++++-- include/linux/clk-provider.h | 26 ++++++ include/linux/clk.h | 33 +++++++ include/trace/events/clk.h | 36 ++++++++ 4 files changed, 289 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 9760b526ca31..b0a2719d86f3 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -68,6 +68,7 @@ struct clk_core { unsigned long max_rate; unsigned long accuracy; int phase; + struct clk_duty duty; struct hlist_head children; struct hlist_node child_node; struct hlist_head clks; @@ -2402,6 +2403,172 @@ int clk_get_phase(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_get_phase); +static void clk_core_reset_duty_cycle_nolock(struct clk_core *core) +{ + /* Assume a default value of 50% */ + core->duty.num = 1; + core->duty.den = 2; +} + +static int clk_core_update_duty_cycle_parent_nolock(struct clk_core *core); + +static int clk_core_update_duty_cycle_nolock(struct clk_core *core) +{ + struct clk_duty *duty = &core->duty; + int ret = 0; + + if (!core->ops->get_duty_cycle) + return clk_core_update_duty_cycle_parent_nolock(core); + + ret = core->ops->get_duty_cycle(core->hw, duty); + if (ret) + goto reset; + + /* Don't trust the clock provider too much */ + if (duty->den == 0 || duty->num > duty->den) { + ret = -EINVAL; + goto reset; + } + + return 0; + +reset: + clk_core_reset_duty_cycle_nolock(core); + return ret; +} + +static int clk_core_update_duty_cycle_parent_nolock(struct clk_core *core) +{ + int ret = 0; + + if (core->parent && + core->flags & CLK_DUTY_CYCLE_PARENT) { + ret = clk_core_update_duty_cycle_nolock(core->parent); + memcpy(&core->duty, &core->parent->duty, sizeof(core->duty)); + } else { + clk_core_reset_duty_cycle_nolock(core); + } + + return ret; +} + +static int clk_core_set_duty_cycle_parent_nolock(struct clk_core *core, + struct clk_duty *duty); + +static int clk_core_set_duty_cycle_nolock(struct clk_core *core, + struct clk_duty *duty) +{ + int ret; + + lockdep_assert_held(&prepare_lock); + + if (clk_core_rate_is_protected(core)) + return -EBUSY; + + trace_clk_set_duty_cycle(core, duty); + + if (!core->ops->set_duty_cycle) + return clk_core_set_duty_cycle_parent_nolock(core, duty); + + ret = core->ops->set_duty_cycle(core->hw, duty); + if (!ret) + memcpy(&core->duty, duty, sizeof(*duty)); + + trace_clk_set_duty_cycle_complete(core, duty); + + return ret; +} + +static int clk_core_set_duty_cycle_parent_nolock(struct clk_core *core, + struct clk_duty *duty) +{ + int ret = 0; + + if (core->parent && + core->flags & (CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT)) { + ret = clk_core_set_duty_cycle_nolock(core->parent, duty); + memcpy(&core->duty, &core->parent->duty, sizeof(core->duty)); + } + + return ret; +} + +/** + * clk_set_duty_cycle - adjust the duty cycle ratio of a clock signal + * @clk: clock signal source + * @num: numerator of the duty cycle ratio to be applied + * @den: denominator of the duty cycle ratio to be applied + * + * Apply the duty cycle ratio if the ratio is valid and the clock can + * perform this operation + * + * Returns (0) on success, a negative errno otherwise. + */ +int clk_set_duty_cycle(struct clk *clk, unsigned int num, unsigned int den) +{ + int ret; + struct clk_duty duty; + + if (!clk) + return 0; + + /* sanity check the ratio */ + if (den == 0 || num > den) + return -EINVAL; + + duty.num = num; + duty.den = den; + + clk_prepare_lock(); + + if (clk->exclusive_count) + clk_core_rate_unprotect(clk->core); + + ret = clk_core_set_duty_cycle_nolock(clk->core, &duty); + + if (clk->exclusive_count) + clk_core_rate_protect(clk->core); + + clk_prepare_unlock(); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_set_duty_cycle); + +static int clk_core_get_scaled_duty_cycle(struct clk_core *core, + unsigned int scale) +{ + struct clk_duty *duty = &core->duty; + int ret; + + clk_prepare_lock(); + + ret = clk_core_update_duty_cycle_nolock(core); + if (!ret) + ret = mult_frac(scale, duty->num, duty->den); + + clk_prepare_unlock(); + + return ret; +} + +/** + * clk_get_scaled_duty_cycle - return the duty cycle ratio of a clock signal + * @clk: clock signal source + * @scale: scaling factor to be applied to represent the ratio as an integer + * + * Returns the duty cycle ratio of a clock node multiplied by the provided + * scaling factor, or negative errno on error. + */ +int clk_get_scaled_duty_cycle(struct clk *clk, unsigned int scale) +{ + if (!clk) + return 0; + + return clk_core_get_scaled_duty_cycle(clk->core, scale); +} +EXPORT_SYMBOL_GPL(clk_get_scaled_duty_cycle); + /** * clk_is_match - check if two clk's point to the same hardware clock * @p: clk compared against q @@ -2455,12 +2622,13 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c, if (!c) return; - seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %-3d\n", + seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %5d %6d\n", level * 3 + 1, "", 30 - level * 3, c->name, c->enable_count, c->prepare_count, c->protect_count, clk_core_get_rate(c), clk_core_get_accuracy(c), - clk_core_get_phase(c)); + clk_core_get_phase(c), + clk_core_get_scaled_duty_cycle(c, 100000)); } static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c, @@ -2482,9 +2650,9 @@ static int clk_summary_show(struct seq_file *s, void *data) struct clk_core *c; struct hlist_head **lists = (struct hlist_head **)s->private; - seq_puts(s, " enable prepare protect \n"); - seq_puts(s, " clock count count count rate accuracy phase\n"); - seq_puts(s, "----------------------------------------------------------------------------------------\n"); + seq_puts(s, " enable prepare protect duty\n"); + seq_puts(s, " clock count count count rate accuracy phase cycle\n"); + seq_puts(s, "---------------------------------------------------------------------------------------------\n"); clk_prepare_lock(); @@ -2511,6 +2679,8 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level) seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c)); seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c)); seq_printf(s, "\"phase\": %d", clk_core_get_phase(c)); + seq_printf(s, "\"duty_cycle\": %u", + clk_core_get_scaled_duty_cycle(c, 100000)); } static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level) @@ -2572,6 +2742,7 @@ static const struct { ENTRY(CLK_SET_RATE_UNGATE), ENTRY(CLK_IS_CRITICAL), ENTRY(CLK_OPS_PARENT_ENABLE), + ENTRY(CLK_DUTY_CYCLE_PARENT), #undef ENTRY }; @@ -2610,6 +2781,17 @@ static int possible_parents_show(struct seq_file *s, void *data) } DEFINE_SHOW_ATTRIBUTE(possible_parents); +static int clk_duty_cycle_show(struct seq_file *s, void *data) +{ + struct clk_core *core = s->private; + struct clk_duty *duty = &core->duty; + + seq_printf(s, "%u/%u\n", duty->num, duty->den); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(clk_duty_cycle); + static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry) { struct dentry *root; @@ -2628,6 +2810,8 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry) debugfs_create_u32("clk_enable_count", 0444, root, &core->enable_count); debugfs_create_u32("clk_protect_count", 0444, root, &core->protect_count); debugfs_create_u32("clk_notifier_count", 0444, root, &core->notifier_count); + debugfs_create_file("clk_duty_cycle", 0444, root, core, + &clk_duty_cycle_fops); if (core->num_parents > 1) debugfs_create_file("clk_possible_parents", 0444, root, core, @@ -2845,6 +3029,11 @@ static int __clk_core_init(struct clk_core *core) else core->phase = 0; + /* + * Set clk's duty cycle. + */ + clk_core_update_duty_cycle_nolock(core); + /* * Set clk's rate. The preferred method is to use .recalc_rate. For * simple clocks and lazy developers the default fallback is to use the diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index b7cfa037e593..08b1aa70a38d 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -38,6 +38,8 @@ #define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ /* parents need enable during gate/ungate, set rate and re-parent */ #define CLK_OPS_PARENT_ENABLE BIT(12) +/* duty cycle call may be forwarded to the parent clock */ +#define CLK_DUTY_CYCLE_PARENT BIT(13) struct clk; struct clk_hw; @@ -66,6 +68,17 @@ struct clk_rate_request { struct clk_hw *best_parent_hw; }; +/** + * struct clk_duty - Struture encoding the duty cycle ratio of a clock + * + * @num: Numerator of the duty cycle ratio + * @den: Denominator of the duty cycle ratio + */ +struct clk_duty { + unsigned int num; + unsigned int den; +}; + /** * struct clk_ops - Callback operations for hardware clocks; these are to * be provided by the clock implementation, and will be called by drivers @@ -169,6 +182,15 @@ struct clk_rate_request { * by the second argument. Valid values for degrees are * 0-359. Return 0 on success, otherwise -EERROR. * + * @get_duty_cycle: Queries the hardware to get the current duty cycle ratio + * of a clock. Returned values denominator cannot be 0 and must be + * superior or equal to the numerator. + * + * @set_duty_cycle: Apply the duty cycle ratio to this clock signal specified by + * the numerator (2nd argurment) and denominator (3rd argument). + * Argument must be a valid ratio (denominator > 0 + * and >= numerator) Return 0 on success, otherwise -EERROR. + * * @init: Perform platform-specific initialization magic. * This is not not used by any of the basic clock types. * Please consider other ways of solving initialization problems @@ -218,6 +240,10 @@ struct clk_ops { unsigned long parent_accuracy); int (*get_phase)(struct clk_hw *hw); int (*set_phase)(struct clk_hw *hw, int degrees); + int (*get_duty_cycle)(struct clk_hw *hw, + struct clk_duty *duty); + int (*set_duty_cycle)(struct clk_hw *hw, + struct clk_duty *duty); void (*init)(struct clk_hw *hw); void (*debug_init)(struct clk_hw *hw, struct dentry *dentry); }; diff --git a/include/linux/clk.h b/include/linux/clk.h index 0dbd0885b2c2..4f750c481b82 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -141,6 +141,27 @@ int clk_set_phase(struct clk *clk, int degrees); */ int clk_get_phase(struct clk *clk); +/** + * clk_set_duty_cycle - adjust the duty cycle ratio of a clock signal + * @clk: clock signal source + * @num: numerator of the duty cycle ratio to be applied + * @den: denominator of the duty cycle ratio to be applied + * + * Adjust the duty cycle of a clock signal by the specified ratio. Returns 0 on + * success, -EERROR otherwise. + */ +int clk_set_duty_cycle(struct clk *clk, unsigned int num, unsigned int den); + +/** + * clk_get_duty_cycle - return the duty cycle ratio of a clock signal + * @clk: clock signal source + * @scale: scaling factor to be applied to represent the ratio as an integer + * + * Returns the duty cycle ratio multiplied by the scale provided, otherwise + * returns -EERROR. + */ +int clk_get_scaled_duty_cycle(struct clk *clk, unsigned int scale); + /** * clk_is_match - check if two clk's point to the same hardware clock * @p: clk compared against q @@ -183,6 +204,18 @@ static inline long clk_get_phase(struct clk *clk) return -ENOTSUPP; } +static inline int clk_set_duty_cycle(struct clk *clk, unsigned int num, + unsigned int den) +{ + return -ENOTSUPP; +} + +static inline unsigned int clk_get_scaled_duty_cycle(struct clk *clk, + unsigned int scale) +{ + return 0; +} + static inline bool clk_is_match(const struct clk *p, const struct clk *q) { return p == q; diff --git a/include/trace/events/clk.h b/include/trace/events/clk.h index 2cd449328aee..9004ffff7f32 100644 --- a/include/trace/events/clk.h +++ b/include/trace/events/clk.h @@ -192,6 +192,42 @@ DEFINE_EVENT(clk_phase, clk_set_phase_complete, TP_ARGS(core, phase) ); +DECLARE_EVENT_CLASS(clk_duty_cycle, + + TP_PROTO(struct clk_core *core, struct clk_duty *duty), + + TP_ARGS(core, duty), + + TP_STRUCT__entry( + __string( name, core->name ) + __field( unsigned int, num ) + __field( unsigned int, den ) + ), + + TP_fast_assign( + __assign_str(name, core->name); + __entry->num = duty->num; + __entry->den = duty->den; + ), + + TP_printk("%s %u/%u", __get_str(name), (unsigned int)__entry->num, + (unsigned int)__entry->den) +); + +DEFINE_EVENT(clk_duty_cycle, clk_set_duty_cycle, + + TP_PROTO(struct clk_core *core, struct clk_duty *duty), + + TP_ARGS(core, duty) +); + +DEFINE_EVENT(clk_duty_cycle, clk_set_duty_cycle_complete, + + TP_PROTO(struct clk_core *core, struct clk_duty *duty), + + TP_ARGS(core, duty) +); + #endif /* _TRACE_CLK_H */ /* This part must be outside protection */ -- cgit v1.2.3 From 4aaf448fa9754e2d5ee188d32327b24ffc15ca4d Mon Sep 17 00:00:00 2001 From: Jim Qu Date: Tue, 17 Jul 2018 16:20:50 +0800 Subject: vga_switcheroo: set audio client id according to bound GPU id On modern laptop, there are more and more platforms have two GPUs, and each of them maybe have audio codec for HDMP/DP output. For some dGPU which is no output, audio codec usually is disabled. In currect HDA audio driver, it will set all codec as VGA_SWITCHEROO_DIS, the audio which is binded to UMA will be suspended if user use debugfs to contorl power In HDA driver side, it is difficult to know which GPU the audio has binded to. So set the bound gpu pci dev to vga_switcheroo. if the audio client is not the third registration, audio id will set in vga_switcheroo enable function. if the audio client is the last registration when vga_switcheroo _ready() get true, we should get audio client id from bound GPU directly. Signed-off-by: Jim Qu Reviewed-by: Lukas Wunner Signed-off-by: Takashi Iwai --- drivers/gpu/vga/vga_switcheroo.c | 63 +++++++++++++++++++++++++++++++++------- include/linux/vga_switcheroo.h | 8 ++--- sound/pci/hda/hda_intel.c | 11 +++---- 3 files changed, 62 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index fc4adf3d34e8..a96bf46bc483 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -103,9 +103,11 @@ * runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs * interface is a no-op so as not to interfere with runtime pm * @list: client list + * @vga_dev: pci device, indicate which GPU is bound to current audio client * * Registered client. A client can be either a GPU or an audio device on a GPU. - * For audio clients, the @fb_info and @active members are bogus. + * For audio clients, the @fb_info and @active members are bogus. For GPU + * clients, the @vga_dev is bogus. */ struct vga_switcheroo_client { struct pci_dev *pdev; @@ -116,6 +118,7 @@ struct vga_switcheroo_client { bool active; bool driver_power_control; struct list_head list; + struct pci_dev *vga_dev; }; /* @@ -161,9 +164,8 @@ struct vgasr_priv { }; #define ID_BIT_AUDIO 0x100 -#define client_is_audio(c) ((c)->id & ID_BIT_AUDIO) -#define client_is_vga(c) ((c)->id == VGA_SWITCHEROO_UNKNOWN_ID || \ - !client_is_audio(c)) +#define client_is_audio(c) ((c)->id & ID_BIT_AUDIO) +#define client_is_vga(c) (!client_is_audio(c)) #define client_id(c) ((c)->id & ~ID_BIT_AUDIO) static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv); @@ -192,14 +194,29 @@ static void vga_switcheroo_enable(void) vgasr_priv.handler->init(); list_for_each_entry(client, &vgasr_priv.clients, list) { - if (client->id != VGA_SWITCHEROO_UNKNOWN_ID) + if (!client_is_vga(client) || + client_id(client) != VGA_SWITCHEROO_UNKNOWN_ID) continue; + ret = vgasr_priv.handler->get_client_id(client->pdev); if (ret < 0) return; client->id = ret; } + + list_for_each_entry(client, &vgasr_priv.clients, list) { + if (!client_is_audio(client) || + client_id(client) != VGA_SWITCHEROO_UNKNOWN_ID) + continue; + + ret = vgasr_priv.handler->get_client_id(client->vga_dev); + if (ret < 0) + return; + + client->id = ret | ID_BIT_AUDIO; + } + vga_switcheroo_debugfs_init(&vgasr_priv); vgasr_priv.active = true; } @@ -272,7 +289,9 @@ EXPORT_SYMBOL(vga_switcheroo_handler_flags); static int register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, - enum vga_switcheroo_client_id id, bool active, + enum vga_switcheroo_client_id id, + struct pci_dev *vga_dev, + bool active, bool driver_power_control) { struct vga_switcheroo_client *client; @@ -287,6 +306,7 @@ static int register_client(struct pci_dev *pdev, client->id = id; client->active = active; client->driver_power_control = driver_power_control; + client->vga_dev = vga_dev; mutex_lock(&vgasr_mutex); list_add_tail(&client->list, &vgasr_priv.clients); @@ -319,7 +339,7 @@ int vga_switcheroo_register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, bool driver_power_control) { - return register_client(pdev, ops, VGA_SWITCHEROO_UNKNOWN_ID, + return register_client(pdev, ops, VGA_SWITCHEROO_UNKNOWN_ID, NULL, pdev == vga_default_device(), driver_power_control); } @@ -329,19 +349,40 @@ EXPORT_SYMBOL(vga_switcheroo_register_client); * vga_switcheroo_register_audio_client - register audio client * @pdev: client pci device * @ops: client callbacks - * @id: client identifier + * @vga_dev: pci device which is bound to current audio client * * Register audio client (audio device on a GPU). The client is assumed * to use runtime PM. Beforehand, vga_switcheroo_client_probe_defer() * shall be called to ensure that all prerequisites are met. * - * Return: 0 on success, -ENOMEM on memory allocation error. + * Return: 0 on success, -ENOMEM on memory allocation error, -EINVAL on getting + * client id error. */ int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, - enum vga_switcheroo_client_id id) + struct pci_dev *vga_dev) { - return register_client(pdev, ops, id | ID_BIT_AUDIO, false, true); + enum vga_switcheroo_client_id id = VGA_SWITCHEROO_UNKNOWN_ID; + + /* + * if vga_switcheroo has enabled, that mean two GPU clients and also + * handler are registered. Get audio client id from bound GPU client + * id directly, otherwise, set it as VGA_SWITCHEROO_UNKNOWN_ID, + * it will set to correct id in later when vga_switcheroo_enable() + * is called. + */ + mutex_lock(&vgasr_mutex); + if (vgasr_priv.active) { + id = vgasr_priv.handler->get_client_id(vga_dev); + if (id < 0) { + mutex_unlock(&vgasr_mutex); + return -EINVAL; + } + } + mutex_unlock(&vgasr_mutex); + + return register_client(pdev, ops, id | ID_BIT_AUDIO, vga_dev, + false, true); } EXPORT_SYMBOL(vga_switcheroo_register_audio_client); diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index 77f0f0af3a71..a34539b7f750 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -84,8 +84,8 @@ enum vga_switcheroo_state { * Client identifier. Audio clients use the same identifier & 0x100. */ enum vga_switcheroo_client_id { - VGA_SWITCHEROO_UNKNOWN_ID = -1, - VGA_SWITCHEROO_IGD, + VGA_SWITCHEROO_UNKNOWN_ID = 0x1000, + VGA_SWITCHEROO_IGD = 0, VGA_SWITCHEROO_DIS, VGA_SWITCHEROO_MAX_CLIENTS, }; @@ -151,7 +151,7 @@ int vga_switcheroo_register_client(struct pci_dev *dev, bool driver_power_control); int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, - enum vga_switcheroo_client_id id); + struct pci_dev *vga_dev); void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info); @@ -180,7 +180,7 @@ static inline int vga_switcheroo_register_handler(const struct vga_switcheroo_ha enum vga_switcheroo_handler_flags_t handler_flags) { return 0; } static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, - enum vga_switcheroo_client_id id) { return 0; } + struct pci_dev *vga_dev) { return 0; } static inline void vga_switcheroo_unregister_handler(void) {} static inline enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void) { return 0; } static inline int vga_switcheroo_lock_ddc(struct pci_dev *pdev) { return -ENODEV; } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1ae1850b3bfd..1967a5537d68 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1319,15 +1319,16 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = { static int register_vga_switcheroo(struct azx *chip) { struct hda_intel *hda = container_of(chip, struct hda_intel, chip); + struct pci_dev *p; int err; if (!hda->use_vga_switcheroo) return 0; - /* FIXME: currently only handling DIS controller - * is there any machine with two switchable HDMI audio controllers? - */ - err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, - VGA_SWITCHEROO_DIS); + + p = get_bound_vga(chip->pci); + err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, p); + pci_dev_put(p); + if (err < 0) return err; hda->vga_switcheroo_registered = 1; -- cgit v1.2.3 From ae891abe7c2ccf75b69ca8330225e37ecc06924e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Jul 2018 15:17:22 +0200 Subject: drm/i915: Split audio component to a generic type For allowing other drivers to use the DRM audio component, rename the i915_audio_component_* with drm_audio_component_*, and split the generic part into drm_audio_component.h. The i915 specific stuff remains in struct i915_audio_component, which contains drm_audio_component as the base. The license of drm_audio_component.h is kept to MIT as same as the the original i915_component.h. This is a preliminary change for further development, and no functional changes by this patch itself, merely code-split and renames. v1->v2: Use SPDX for drm_audio_component.h, fix remaining i915 argument in drm_audio_component.h Reviewed-by: Rodrigo Vivi Signed-off-by: Takashi Iwai --- drivers/gpu/drm/i915/intel_audio.c | 22 +++++---- include/drm/drm_audio_component.h | 95 ++++++++++++++++++++++++++++++++++++++ include/drm/i915_component.h | 85 ++-------------------------------- include/sound/hda_i915.h | 6 +-- include/sound/hdaudio.h | 6 +-- sound/hda/hdac_i915.c | 40 ++++++++-------- sound/pci/hda/patch_hdmi.c | 8 ++-- sound/soc/codecs/hdac_hdmi.c | 2 +- 8 files changed, 144 insertions(+), 120 deletions(-) create mode 100644 include/drm/drm_audio_component.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 3ea566f99450..7dd5605d94ae 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -639,11 +639,12 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, dev_priv->av_enc_map[pipe] = encoder; mutex_unlock(&dev_priv->av_mutex); - if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) { + if (acomp && acomp->base.audio_ops && + acomp->base.audio_ops->pin_eld_notify) { /* audio drivers expect pipe = -1 to indicate Non-MST cases */ if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) pipe = -1; - acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, + acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr, (int) port, (int) pipe); } @@ -681,11 +682,12 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, dev_priv->av_enc_map[pipe] = NULL; mutex_unlock(&dev_priv->av_mutex); - if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) { + if (acomp && acomp->base.audio_ops && + acomp->base.audio_ops->pin_eld_notify) { /* audio drivers expect pipe = -1 to indicate Non-MST cases */ if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) pipe = -1; - acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, + acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr, (int) port, (int) pipe); } @@ -880,7 +882,7 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, return ret; } -static const struct i915_audio_component_ops i915_audio_component_ops = { +static const struct drm_audio_component_ops i915_audio_component_ops = { .owner = THIS_MODULE, .get_power = i915_audio_component_get_power, .put_power = i915_audio_component_put_power, @@ -897,12 +899,12 @@ static int i915_audio_component_bind(struct device *i915_kdev, struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev); int i; - if (WARN_ON(acomp->ops || acomp->dev)) + if (WARN_ON(acomp->base.ops || acomp->base.dev)) return -EEXIST; drm_modeset_lock_all(&dev_priv->drm); - acomp->ops = &i915_audio_component_ops; - acomp->dev = i915_kdev; + acomp->base.ops = &i915_audio_component_ops; + acomp->base.dev = i915_kdev; BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS); for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++) acomp->aud_sample_rate[i] = 0; @@ -919,8 +921,8 @@ static void i915_audio_component_unbind(struct device *i915_kdev, struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev); drm_modeset_lock_all(&dev_priv->drm); - acomp->ops = NULL; - acomp->dev = NULL; + acomp->base.ops = NULL; + acomp->base.dev = NULL; dev_priv->audio_component = NULL; drm_modeset_unlock_all(&dev_priv->drm); } diff --git a/include/drm/drm_audio_component.h b/include/drm/drm_audio_component.h new file mode 100644 index 000000000000..e85689f212c2 --- /dev/null +++ b/include/drm/drm_audio_component.h @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2014 Intel Corporation + +#ifndef _DRM_AUDIO_COMPONENT_H_ +#define _DRM_AUDIO_COMPONENT_H_ + +/** + * struct drm_audio_component_ops - Ops implemented by DRM driver, called by hda driver + */ +struct drm_audio_component_ops { + /** + * @owner: drm module to pin down + */ + struct module *owner; + /** + * @get_power: get the POWER_DOMAIN_AUDIO power well + * + * Request the power well to be turned on. + */ + void (*get_power)(struct device *); + /** + * @put_power: put the POWER_DOMAIN_AUDIO power well + * + * Allow the power well to be turned off. + */ + void (*put_power)(struct device *); + /** + * @codec_wake_override: Enable/disable codec wake signal + */ + void (*codec_wake_override)(struct device *, bool enable); + /** + * @get_cdclk_freq: Get the Core Display Clock in kHz + */ + int (*get_cdclk_freq)(struct device *); + /** + * @sync_audio_rate: set n/cts based on the sample rate + * + * Called from audio driver. After audio driver sets the + * sample rate, it will call this function to set n/cts + */ + int (*sync_audio_rate)(struct device *, int port, int pipe, int rate); + /** + * @get_eld: fill the audio state and ELD bytes for the given port + * + * Called from audio driver to get the HDMI/DP audio state of the given + * digital port, and also fetch ELD bytes to the given pointer. + * + * It returns the byte size of the original ELD (not the actually + * copied size), zero for an invalid ELD, or a negative error code. + * + * Note that the returned size may be over @max_bytes. Then it + * implies that only a part of ELD has been copied to the buffer. + */ + int (*get_eld)(struct device *, int port, int pipe, bool *enabled, + unsigned char *buf, int max_bytes); +}; + +/** + * struct drm_audio_component_audio_ops - Ops implemented by hda driver, called by DRM driver + */ +struct drm_audio_component_audio_ops { + /** + * @audio_ptr: Pointer to be used in call to pin_eld_notify + */ + void *audio_ptr; + /** + * @pin_eld_notify: Notify the HDA driver that pin sense and/or ELD information has changed + * + * Called when the DRM driver has set up audio pipeline or has just + * begun to tear it down. This allows the HDA driver to update its + * status accordingly (even when the HDA controller is in power save + * mode). + */ + void (*pin_eld_notify)(void *audio_ptr, int port, int pipe); +}; + +/** + * struct drm_audio_component - Used for direct communication between DRM and hda drivers + */ +struct drm_audio_component { + /** + * @dev: DRM device, used as parameter for ops + */ + struct device *dev; + /** + * @ops: Ops implemented by DRM driver, called by hda driver + */ + const struct drm_audio_component_ops *ops; + /** + * @audio_ops: Ops implemented by hda driver, called by DRM driver + */ + const struct drm_audio_component_audio_ops *audio_ops; +}; + +#endif /* _DRM_AUDIO_COMPONENT_H_ */ diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h index 346b1f5cb180..fca22d463e1b 100644 --- a/include/drm/i915_component.h +++ b/include/drm/i915_component.h @@ -24,101 +24,26 @@ #ifndef _I915_COMPONENT_H_ #define _I915_COMPONENT_H_ +#include "drm_audio_component.h" + /* MAX_PORT is the number of port * It must be sync with I915_MAX_PORTS defined i915_drv.h */ #define MAX_PORTS 6 -/** - * struct i915_audio_component_ops - Ops implemented by i915 driver, called by hda driver - */ -struct i915_audio_component_ops { - /** - * @owner: i915 module - */ - struct module *owner; - /** - * @get_power: get the POWER_DOMAIN_AUDIO power well - * - * Request the power well to be turned on. - */ - void (*get_power)(struct device *); - /** - * @put_power: put the POWER_DOMAIN_AUDIO power well - * - * Allow the power well to be turned off. - */ - void (*put_power)(struct device *); - /** - * @codec_wake_override: Enable/disable codec wake signal - */ - void (*codec_wake_override)(struct device *, bool enable); - /** - * @get_cdclk_freq: Get the Core Display Clock in kHz - */ - int (*get_cdclk_freq)(struct device *); - /** - * @sync_audio_rate: set n/cts based on the sample rate - * - * Called from audio driver. After audio driver sets the - * sample rate, it will call this function to set n/cts - */ - int (*sync_audio_rate)(struct device *, int port, int pipe, int rate); - /** - * @get_eld: fill the audio state and ELD bytes for the given port - * - * Called from audio driver to get the HDMI/DP audio state of the given - * digital port, and also fetch ELD bytes to the given pointer. - * - * It returns the byte size of the original ELD (not the actually - * copied size), zero for an invalid ELD, or a negative error code. - * - * Note that the returned size may be over @max_bytes. Then it - * implies that only a part of ELD has been copied to the buffer. - */ - int (*get_eld)(struct device *, int port, int pipe, bool *enabled, - unsigned char *buf, int max_bytes); -}; - -/** - * struct i915_audio_component_audio_ops - Ops implemented by hda driver, called by i915 driver - */ -struct i915_audio_component_audio_ops { - /** - * @audio_ptr: Pointer to be used in call to pin_eld_notify - */ - void *audio_ptr; - /** - * @pin_eld_notify: Notify the HDA driver that pin sense and/or ELD information has changed - * - * Called when the i915 driver has set up audio pipeline or has just - * begun to tear it down. This allows the HDA driver to update its - * status accordingly (even when the HDA controller is in power save - * mode). - */ - void (*pin_eld_notify)(void *audio_ptr, int port, int pipe); -}; - /** * struct i915_audio_component - Used for direct communication between i915 and hda drivers */ struct i915_audio_component { /** - * @dev: i915 device, used as parameter for ops + * @base: the drm_audio_component base class */ - struct device *dev; + struct drm_audio_component base; + /** * @aud_sample_rate: the array of audio sample rate per port */ int aud_sample_rate[MAX_PORTS]; - /** - * @ops: Ops implemented by i915 driver, called by hda driver - */ - const struct i915_audio_component_ops *ops; - /** - * @audio_ops: Ops implemented by hda driver, called by i915 driver - */ - const struct i915_audio_component_audio_ops *audio_ops; }; #endif /* _I915_COMPONENT_H_ */ diff --git a/include/sound/hda_i915.h b/include/sound/hda_i915.h index a94f5b6f92ac..f69ea84e7b65 100644 --- a/include/sound/hda_i915.h +++ b/include/sound/hda_i915.h @@ -5,7 +5,7 @@ #ifndef __SOUND_HDA_I915_H #define __SOUND_HDA_I915_H -#include +#include #ifdef CONFIG_SND_HDA_I915 int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); @@ -17,7 +17,7 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, bool *audio_enabled, char *buffer, int max_bytes); int snd_hdac_i915_init(struct hdac_bus *bus); int snd_hdac_i915_exit(struct hdac_bus *bus); -int snd_hdac_i915_register_notifier(const struct i915_audio_component_audio_ops *); +int snd_hdac_i915_register_notifier(const struct drm_audio_component_audio_ops *); #else static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) { @@ -49,7 +49,7 @@ static inline int snd_hdac_i915_exit(struct hdac_bus *bus) { return 0; } -static inline int snd_hdac_i915_register_notifier(const struct i915_audio_component_audio_ops *ops) +static inline int snd_hdac_i915_register_notifier(const struct drm_audio_component_audio_ops *ops) { return -ENODEV; } diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index f1baaa88e766..ab5ee3ef2198 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -333,9 +333,9 @@ struct hdac_bus { spinlock_t reg_lock; struct mutex cmd_mutex; - /* i915 component interface */ - struct i915_audio_component *audio_component; - int i915_power_refcount; + /* DRM component interface */ + struct drm_audio_component *audio_component; + int drm_power_refcount; /* parameters required for enhanced capabilities */ int num_streams; diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index cbe818eda336..1a88c1aaf9bb 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -16,13 +16,13 @@ #include #include #include -#include +#include #include #include #include #include -static struct i915_audio_component *hdac_acomp; +static struct drm_audio_component *hdac_acomp; /** * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup @@ -39,7 +39,7 @@ static struct i915_audio_component *hdac_acomp; */ int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) { - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; if (!acomp || !acomp->ops) return -ENODEV; @@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); */ int snd_hdac_display_power(struct hdac_bus *bus, bool enable) { - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; if (!acomp || !acomp->ops) return -ENODEV; @@ -83,14 +83,14 @@ int snd_hdac_display_power(struct hdac_bus *bus, bool enable) enable ? "enable" : "disable"); if (enable) { - if (!bus->i915_power_refcount++) { + if (!bus->drm_power_refcount++) { acomp->ops->get_power(acomp->dev); snd_hdac_set_codec_wakeup(bus, true); snd_hdac_set_codec_wakeup(bus, false); } } else { - WARN_ON(!bus->i915_power_refcount); - if (!--bus->i915_power_refcount) + WARN_ON(!bus->drm_power_refcount); + if (!--bus->drm_power_refcount) acomp->ops->put_power(acomp->dev); } @@ -119,7 +119,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_display_power); */ void snd_hdac_i915_set_bclk(struct hdac_bus *bus) { - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; struct pci_dev *pci = to_pci_dev(bus->dev); int cdclk_freq; unsigned int bclk_m, bclk_n; @@ -206,7 +206,7 @@ int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int dev_id, int rate) { struct hdac_bus *bus = codec->bus; - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; int port, pipe; if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate) @@ -244,7 +244,7 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, bool *audio_enabled, char *buffer, int max_bytes) { struct hdac_bus *bus = codec->bus; - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; int port, pipe; if (!acomp || !acomp->ops || !acomp->ops->get_eld) @@ -262,7 +262,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); static int hdac_component_master_bind(struct device *dev) { - struct i915_audio_component *acomp = hdac_acomp; + struct drm_audio_component *acomp = hdac_acomp; int ret; ret = component_bind_all(dev, acomp); @@ -294,7 +294,7 @@ out_unbind: static void hdac_component_master_unbind(struct device *dev) { - struct i915_audio_component *acomp = hdac_acomp; + struct drm_audio_component *acomp = hdac_acomp; module_put(acomp->ops->owner); component_unbind_all(dev, acomp); @@ -323,7 +323,7 @@ static int hdac_component_master_match(struct device *dev, void *data) * * Returns zero for success or a negative error code. */ -int snd_hdac_i915_register_notifier(const struct i915_audio_component_audio_ops *aops) +int snd_hdac_i915_register_notifier(const struct drm_audio_component_audio_ops *aops) { if (!hdac_acomp) return -ENODEV; @@ -361,7 +361,8 @@ int snd_hdac_i915_init(struct hdac_bus *bus) { struct component_match *match = NULL; struct device *dev = bus->dev; - struct i915_audio_component *acomp; + struct i915_audio_component *i915_acomp; + struct drm_audio_component *acomp; int ret; if (WARN_ON(hdac_acomp)) @@ -370,9 +371,10 @@ int snd_hdac_i915_init(struct hdac_bus *bus) if (!i915_gfx_present()) return -ENODEV; - acomp = kzalloc(sizeof(*acomp), GFP_KERNEL); - if (!acomp) + i915_acomp = kzalloc(sizeof(*i915_acomp), GFP_KERNEL); + if (!i915_acomp) return -ENOMEM; + acomp = &i915_acomp->base; bus->audio_component = acomp; hdac_acomp = acomp; @@ -421,13 +423,13 @@ EXPORT_SYMBOL_GPL(snd_hdac_i915_init); int snd_hdac_i915_exit(struct hdac_bus *bus) { struct device *dev = bus->dev; - struct i915_audio_component *acomp = bus->audio_component; + struct drm_audio_component *acomp = bus->audio_component; if (!acomp) return 0; - WARN_ON(bus->i915_power_refcount); - if (bus->i915_power_refcount > 0 && acomp->ops) + WARN_ON(bus->drm_power_refcount); + if (bus->drm_power_refcount > 0 && acomp->ops) acomp->ops->put_power(acomp->dev); component_master_del(dev, &hdac_component_master_ops); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8a49415aebac..c0847017114c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -177,7 +177,7 @@ struct hdmi_spec { /* i915/powerwell (Haswell+/Valleyview+) specific */ bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ - struct i915_audio_component_audio_ops i915_audio_ops; + struct drm_audio_component_audio_ops drm_audio_ops; struct hdac_chmap chmap; hda_nid_t vendor_nid; @@ -2511,14 +2511,14 @@ static void register_i915_notifier(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; spec->use_acomp_notifier = true; - spec->i915_audio_ops.audio_ptr = codec; + spec->drm_audio_ops.audio_ptr = codec; /* intel_audio_codec_enable() or intel_audio_codec_disable() * will call pin_eld_notify with using audio_ptr pointer * We need make sure audio_ptr is really setup */ wmb(); - spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify; - snd_hdac_i915_register_notifier(&spec->i915_audio_ops); + spec->drm_audio_ops.pin_eld_notify = intel_pin_eld_notify; + snd_hdac_i915_register_notifier(&spec->drm_audio_ops); } /* setup_stream ops override for HSW+ */ diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 3e3a2a9ef310..460075475f20 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1583,7 +1583,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) } -static struct i915_audio_component_audio_ops aops = { +static struct drm_audio_component_audio_ops aops = { .pin_eld_notify = hdac_hdmi_eld_notify_cb, }; -- cgit v1.2.3 From a57942bfdd61b46df94021c9c33b8faaae5b65e1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Jul 2018 16:23:16 +0200 Subject: ALSA: hda: Make audio component support more generic This is the final step for more generic support of DRM audio component. The generic audio component code is now moved to its own file, and the symbols are renamed from snd_hac_i915_* to snd_hdac_acomp_*, respectively. The generic code is enabled via the new kconfig, CONFIG_SND_HDA_COMPONENT, while CONFIG_SND_HDA_I915 is kept as the super-class. Along with the split, three new callbacks are added to audio_ops: pin2port is for providing the conversion between the pin number and the widget id, and master_bind/master_unbin are called at binding / unbinding the master component, respectively. All these are optional, but used in i915 implementation and also other later implementations. A note about the new snd_hdac_acomp_init() function: there is a slight difference between this and the old snd_hdac_i915_init(). The latter (still) synchronizes with the master component binding, i.e. it assures that the relevant DRM component gets bound when it returns, or gives a negative error. Meanwhile the new function doesn't synchronize but just leaves as is. It's the responsibility by the caller's side to synchronize, or the caller may accept the asynchronous binding on the fly. v1->v2: Fix missing NULL check in master_bind/unbind Signed-off-by: Takashi Iwai --- drivers/gpu/drm/i915/Kconfig | 1 + include/drm/drm_audio_component.h | 23 +++ include/sound/hda_component.h | 61 +++++++ include/sound/hda_i915.h | 39 +---- sound/hda/Kconfig | 7 +- sound/hda/Makefile | 1 + sound/hda/hdac_component.c | 335 +++++++++++++++++++++++++++++++++++++ sound/hda/hdac_i915.c | 343 ++------------------------------------ sound/pci/hda/patch_hdmi.c | 50 ++++-- sound/soc/codecs/hdac_hdmi.c | 8 +- 10 files changed, 486 insertions(+), 382 deletions(-) create mode 100644 include/sound/hda_component.h create mode 100644 sound/hda/hdac_component.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index dfd95889f4b7..5c607f2c707b 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -23,6 +23,7 @@ config DRM_I915 select SYNC_FILE select IOSF_MBI select CRC32 + select SND_HDA_I915 if SND_HDA_CORE help Choose this option if you have a system that has "Intel Graphics Media Accelerator" or "HD Graphics" integrated graphics, diff --git a/include/drm/drm_audio_component.h b/include/drm/drm_audio_component.h index e85689f212c2..4923b00328c1 100644 --- a/include/drm/drm_audio_component.h +++ b/include/drm/drm_audio_component.h @@ -4,6 +4,8 @@ #ifndef _DRM_AUDIO_COMPONENT_H_ #define _DRM_AUDIO_COMPONENT_H_ +struct drm_audio_component; + /** * struct drm_audio_component_ops - Ops implemented by DRM driver, called by hda driver */ @@ -72,6 +74,27 @@ struct drm_audio_component_audio_ops { * mode). */ void (*pin_eld_notify)(void *audio_ptr, int port, int pipe); + /** + * @pin2port: Check and convert from pin node to port number + * + * Called by HDA driver to check and convert from the pin widget node + * number to a port number in the graphics side. + */ + int (*pin2port)(void *audio_ptr, int pin); + /** + * @master_bind: (Optional) component master bind callback + * + * Called at binding master component, for HDA codec-specific + * handling of dynamic binding. + */ + int (*master_bind)(struct device *dev, struct drm_audio_component *); + /** + * @master_unbind: (Optional) component master unbind callback + * + * Called at unbinding master component, for HDA codec-specific + * handling of dynamic unbinding. + */ + void (*master_unbind)(struct device *dev, struct drm_audio_component *); }; /** diff --git a/include/sound/hda_component.h b/include/sound/hda_component.h new file mode 100644 index 000000000000..78626cde7081 --- /dev/null +++ b/include/sound/hda_component.h @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 +// HD-Audio helpers to sync with DRM driver + +#ifndef __SOUND_HDA_COMPONENT_H +#define __SOUND_HDA_COMPONENT_H + +#include + +#ifdef CONFIG_SND_HDA_COMPONENT +int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); +int snd_hdac_display_power(struct hdac_bus *bus, bool enable); +int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, + int dev_id, int rate); +int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, + bool *audio_enabled, char *buffer, int max_bytes); +int snd_hdac_acomp_init(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *aops, + int (*match_master)(struct device *, void *), + size_t extra_size); +int snd_hdac_acomp_exit(struct hdac_bus *bus); +int snd_hdac_acomp_register_notifier(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *ops); +#else +static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) +{ + return 0; +} +static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable) +{ + return 0; +} +static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec, + hda_nid_t nid, int dev_id, int rate) +{ + return 0; +} +static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, + int dev_id, bool *audio_enabled, + char *buffer, int max_bytes) +{ + return -ENODEV; +} +static inline int snd_hdac_acomp_init(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *aops, + int (*match_master)(struct device *, void *), + size_t extra_size) +{ + return -ENODEV; +} +static inline int snd_hdac_acomp_exit(struct hdac_bus *bus) +{ + return 0; +} +static inline int snd_hdac_acomp_register_notifier(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *ops) +{ + return -ENODEV; +} +#endif + +#endif /* __SOUND_HDA_COMPONENT_H */ diff --git a/include/sound/hda_i915.h b/include/sound/hda_i915.h index 648263791559..6b79614a893b 100644 --- a/include/sound/hda_i915.h +++ b/include/sound/hda_i915.h @@ -5,56 +5,23 @@ #ifndef __SOUND_HDA_I915_H #define __SOUND_HDA_I915_H -#include +#include "hda_component.h" #ifdef CONFIG_SND_HDA_I915 -int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); -int snd_hdac_display_power(struct hdac_bus *bus, bool enable); void snd_hdac_i915_set_bclk(struct hdac_bus *bus); -int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, - int dev_id, int rate); -int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, - bool *audio_enabled, char *buffer, int max_bytes); int snd_hdac_i915_init(struct hdac_bus *bus); -int snd_hdac_i915_exit(struct hdac_bus *bus); -int snd_hdac_i915_register_notifier(struct hdac_bus *bus, - const struct drm_audio_component_audio_ops *ops); #else -static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) -{ - return 0; -} -static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable) -{ - return 0; -} static inline void snd_hdac_i915_set_bclk(struct hdac_bus *bus) { } -static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec, - hda_nid_t nid, int dev_id, int rate) -{ - return 0; -} -static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, - int dev_id, bool *audio_enabled, - char *buffer, int max_bytes) -{ - return -ENODEV; -} static inline int snd_hdac_i915_init(struct hdac_bus *bus) { return -ENODEV; } +#endif static inline int snd_hdac_i915_exit(struct hdac_bus *bus) { - return 0; + return snd_hdac_acomp_exit(bus); } -static inline int snd_hdac_i915_register_notifier(struct hdac_bus *bus, - const struct drm_audio_component_audio_ops *ops) -{ - return -ENODEV; -} -#endif #endif /* __SOUND_HDA_I915_H */ diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig index 3129546398d0..2d90e11b3eaa 100644 --- a/sound/hda/Kconfig +++ b/sound/hda/Kconfig @@ -5,11 +5,12 @@ config SND_HDA_CORE config SND_HDA_DSP_LOADER bool +config SND_HDA_COMPONENT + bool + config SND_HDA_I915 bool - default y - depends on DRM_I915 - depends on SND_HDA_CORE + select SND_HDA_COMPONENT config SND_HDA_EXT_CORE tristate diff --git a/sound/hda/Makefile b/sound/hda/Makefile index e4e726f2ce98..2160202e2dc1 100644 --- a/sound/hda/Makefile +++ b/sound/hda/Makefile @@ -6,6 +6,7 @@ snd-hda-core-objs += trace.o CFLAGS_trace.o := -I$(src) # for sync with i915 gfx driver +snd-hda-core-$(CONFIG_SND_HDA_COMPONENT) += hdac_component.o snd-hda-core-$(CONFIG_SND_HDA_I915) += hdac_i915.o obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c new file mode 100644 index 000000000000..6e46a9c73aed --- /dev/null +++ b/sound/hda/hdac_component.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0 +// hdac_component.c - routines for sync between HD-A core and DRM driver + +#include +#include +#include +#include +#include +#include +#include +#include + +static void hdac_acomp_release(struct device *dev, void *res) +{ +} + +static struct drm_audio_component *hdac_get_acomp(struct device *dev) +{ + return devres_find(dev, hdac_acomp_release, NULL, NULL); +} + +/** + * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup + * @bus: HDA core bus + * @enable: enable or disable the wakeup + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function should be called during the chip reset, also called at + * resume for updating STATESTS register read. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) +{ + struct drm_audio_component *acomp = bus->audio_component; + + if (!acomp || !acomp->ops) + return -ENODEV; + + if (!acomp->ops->codec_wake_override) + return 0; + + dev_dbg(bus->dev, "%s codec wakeup\n", + enable ? "enable" : "disable"); + + acomp->ops->codec_wake_override(acomp->dev, enable); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); + +/** + * snd_hdac_display_power - Power up / down the power refcount + * @bus: HDA core bus + * @enable: power up or down + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function manages a refcount and calls the get_power() and + * put_power() ops accordingly, toggling the codec wakeup, too. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_display_power(struct hdac_bus *bus, bool enable) +{ + struct drm_audio_component *acomp = bus->audio_component; + + if (!acomp || !acomp->ops) + return -ENODEV; + + dev_dbg(bus->dev, "display power %s\n", + enable ? "enable" : "disable"); + + if (enable) { + if (!bus->drm_power_refcount++) { + if (acomp->ops->get_power) + acomp->ops->get_power(acomp->dev); + snd_hdac_set_codec_wakeup(bus, true); + snd_hdac_set_codec_wakeup(bus, false); + } + } else { + WARN_ON(!bus->drm_power_refcount); + if (!--bus->drm_power_refcount) + if (acomp->ops->put_power) + acomp->ops->put_power(acomp->dev); + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_display_power); + +/** + * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate + * @codec: HDA codec + * @nid: the pin widget NID + * @dev_id: device identifier + * @rate: the sample rate to set + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function sets N/CTS value based on the given sample rate. + * Returns zero for success, or a negative error code. + */ +int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, + int dev_id, int rate) +{ + struct hdac_bus *bus = codec->bus; + struct drm_audio_component *acomp = bus->audio_component; + int port, pipe; + + if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate) + return -ENODEV; + port = nid; + if (acomp->audio_ops && acomp->audio_ops->pin2port) { + port = acomp->audio_ops->pin2port(codec, nid); + if (port < 0) + return -EINVAL; + } + pipe = dev_id; + return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate); +} +EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); + +/** + * snd_hdac_acomp_get_eld - Get the audio state and ELD via component + * @codec: HDA codec + * @nid: the pin widget NID + * @dev_id: device identifier + * @audio_enabled: the pointer to store the current audio state + * @buffer: the buffer pointer to store ELD bytes + * @max_bytes: the max bytes to be stored on @buffer + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function queries the current state of the audio on the given + * digital port and fetches the ELD bytes onto the given buffer. + * It returns the number of bytes for the total ELD data, zero for + * invalid ELD, or a negative error code. + * + * The return size is the total bytes required for the whole ELD bytes, + * thus it may be over @max_bytes. If it's over @max_bytes, it implies + * that only a part of ELD bytes have been fetched. + */ +int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, + bool *audio_enabled, char *buffer, int max_bytes) +{ + struct hdac_bus *bus = codec->bus; + struct drm_audio_component *acomp = bus->audio_component; + int port, pipe; + + if (!acomp || !acomp->ops || !acomp->ops->get_eld) + return -ENODEV; + + port = nid; + if (acomp->audio_ops && acomp->audio_ops->pin2port) { + port = acomp->audio_ops->pin2port(codec, nid); + if (port < 0) + return -EINVAL; + } + pipe = dev_id; + return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled, + buffer, max_bytes); +} +EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); + +static int hdac_component_master_bind(struct device *dev) +{ + struct drm_audio_component *acomp = hdac_get_acomp(dev); + int ret; + + if (WARN_ON(!acomp)) + return -EINVAL; + + ret = component_bind_all(dev, acomp); + if (ret < 0) + return ret; + + if (WARN_ON(!(acomp->dev && acomp->ops))) { + ret = -EINVAL; + goto out_unbind; + } + + /* pin the module to avoid dynamic unbinding, but only if given */ + if (!try_module_get(acomp->ops->owner)) { + ret = -ENODEV; + goto out_unbind; + } + + if (acomp->audio_ops && acomp->audio_ops->master_bind) { + ret = acomp->audio_ops->master_bind(dev, acomp); + if (ret < 0) + goto module_put; + } + + return 0; + + module_put: + module_put(acomp->ops->owner); +out_unbind: + component_unbind_all(dev, acomp); + + return ret; +} + +static void hdac_component_master_unbind(struct device *dev) +{ + struct drm_audio_component *acomp = hdac_get_acomp(dev); + + if (acomp->audio_ops && acomp->audio_ops->master_unbind) + acomp->audio_ops->master_unbind(dev, acomp); + module_put(acomp->ops->owner); + component_unbind_all(dev, acomp); + WARN_ON(acomp->ops || acomp->dev); +} + +static const struct component_master_ops hdac_component_master_ops = { + .bind = hdac_component_master_bind, + .unbind = hdac_component_master_unbind, +}; + +/** + * snd_hdac_acomp_register_notifier - Register audio component ops + * @bus: HDA core bus + * @aops: audio component ops + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function sets the given ops to be called by the graphics driver. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_acomp_register_notifier(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *aops) +{ + if (!bus->audio_component) + return -ENODEV; + + bus->audio_component->audio_ops = aops; + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier); + +/** + * snd_hdac_acomp_init - Initialize audio component + * @bus: HDA core bus + * @match_master: match function for finding components + * @extra_size: Extra bytes to allocate + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function initializes and sets up the audio component to communicate + * with graphics driver. + * + * Unlike snd_hdac_i915_init(), this function doesn't synchronize with the + * binding with the DRM component. Each caller needs to sync via master_bind + * audio_ops. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_acomp_init(struct hdac_bus *bus, + const struct drm_audio_component_audio_ops *aops, + int (*match_master)(struct device *, void *), + size_t extra_size) +{ + struct component_match *match = NULL; + struct device *dev = bus->dev; + struct drm_audio_component *acomp; + int ret; + + if (WARN_ON(hdac_get_acomp(dev))) + return -EBUSY; + + acomp = devres_alloc(hdac_acomp_release, sizeof(*acomp) + extra_size, + GFP_KERNEL); + if (!acomp) + return -ENOMEM; + acomp->audio_ops = aops; + bus->audio_component = acomp; + devres_add(dev, acomp); + + component_match_add(dev, &match, match_master, bus); + ret = component_master_add_with_match(dev, &hdac_component_master_ops, + match); + if (ret < 0) + goto out_err; + + return 0; + +out_err: + bus->audio_component = NULL; + devres_destroy(dev, hdac_acomp_release, NULL, NULL); + dev_info(dev, "failed to add audio component master (%d)\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_hdac_acomp_init); + +/** + * snd_hdac_acomp_exit - Finalize audio component + * @bus: HDA core bus + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function releases the audio component that has been used. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_acomp_exit(struct hdac_bus *bus) +{ + struct device *dev = bus->dev; + struct drm_audio_component *acomp = bus->audio_component; + + if (!acomp) + return 0; + + WARN_ON(bus->drm_power_refcount); + if (bus->drm_power_refcount > 0 && acomp->ops) + acomp->ops->put_power(acomp->dev); + + component_master_del(dev, &hdac_component_master_ops); + + bus->audio_component = NULL; + devres_destroy(dev, hdac_acomp_release, NULL, NULL); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_acomp_exit); diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index 861b77bbc7df..8f2aa8bc1185 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -15,96 +15,11 @@ #include #include #include -#include -#include #include #include #include #include -static void hdac_acomp_release(struct device *dev, void *res) -{ -} - -static struct drm_audio_component *hdac_get_acomp(struct device *dev) -{ - return devres_find(dev, hdac_acomp_release, NULL, NULL); -} - -/** - * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup - * @bus: HDA core bus - * @enable: enable or disable the wakeup - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function should be called during the chip reset, also called at - * resume for updating STATESTS register read. - * - * Returns zero for success or a negative error code. - */ -int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) -{ - struct drm_audio_component *acomp = bus->audio_component; - - if (!acomp || !acomp->ops) - return -ENODEV; - - if (!acomp->ops->codec_wake_override) { - dev_warn(bus->dev, - "Invalid codec wake callback\n"); - return 0; - } - - dev_dbg(bus->dev, "%s codec wakeup\n", - enable ? "enable" : "disable"); - - acomp->ops->codec_wake_override(acomp->dev, enable); - - return 0; -} -EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); - -/** - * snd_hdac_display_power - Power up / down the power refcount - * @bus: HDA core bus - * @enable: power up or down - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function manages a refcount and calls the i915 get_power() and - * put_power() ops accordingly, toggling the codec wakeup, too. - * - * Returns zero for success or a negative error code. - */ -int snd_hdac_display_power(struct hdac_bus *bus, bool enable) -{ - struct drm_audio_component *acomp = bus->audio_component; - - if (!acomp || !acomp->ops) - return -ENODEV; - - dev_dbg(bus->dev, "display power %s\n", - enable ? "enable" : "disable"); - - if (enable) { - if (!bus->drm_power_refcount++) { - acomp->ops->get_power(acomp->dev); - snd_hdac_set_codec_wakeup(bus, true); - snd_hdac_set_codec_wakeup(bus, false); - } - } else { - WARN_ON(!bus->drm_power_refcount); - if (!--bus->drm_power_refcount) - acomp->ops->put_power(acomp->dev); - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_hdac_display_power); - #define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \ ((pci)->device == 0x0c0c) || \ ((pci)->device == 0x0d0c) || \ @@ -165,183 +80,11 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus) } EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk); -/* There is a fixed mapping between audio pin node and display port. - * on SNB, IVY, HSW, BSW, SKL, BXT, KBL: - * Pin Widget 5 - PORT B (port = 1 in i915 driver) - * Pin Widget 6 - PORT C (port = 2 in i915 driver) - * Pin Widget 7 - PORT D (port = 3 in i915 driver) - * - * on VLV, ILK: - * Pin Widget 4 - PORT B (port = 1 in i915 driver) - * Pin Widget 5 - PORT C (port = 2 in i915 driver) - * Pin Widget 6 - PORT D (port = 3 in i915 driver) - */ -static int pin2port(struct hdac_device *codec, hda_nid_t pin_nid) -{ - int base_nid; - - switch (codec->vendor_id) { - case 0x80860054: /* ILK */ - case 0x80862804: /* ILK */ - case 0x80862882: /* VLV */ - base_nid = 3; - break; - default: - base_nid = 4; - break; - } - - if (WARN_ON(pin_nid <= base_nid || pin_nid > base_nid + 3)) - return -1; - return pin_nid - base_nid; -} - -/** - * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate - * @codec: HDA codec - * @nid: the pin widget NID - * @dev_id: device identifier - * @rate: the sample rate to set - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function sets N/CTS value based on the given sample rate. - * Returns zero for success, or a negative error code. - */ -int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, - int dev_id, int rate) +static int i915_component_master_match(struct device *dev, void *data) { - struct hdac_bus *bus = codec->bus; - struct drm_audio_component *acomp = bus->audio_component; - int port, pipe; - - if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate) - return -ENODEV; - port = pin2port(codec, nid); - if (port < 0) - return -EINVAL; - pipe = dev_id; - return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate); -} -EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); - -/** - * snd_hdac_acomp_get_eld - Get the audio state and ELD via component - * @codec: HDA codec - * @nid: the pin widget NID - * @dev_id: device identifier - * @audio_enabled: the pointer to store the current audio state - * @buffer: the buffer pointer to store ELD bytes - * @max_bytes: the max bytes to be stored on @buffer - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function queries the current state of the audio on the given - * digital port and fetches the ELD bytes onto the given buffer. - * It returns the number of bytes for the total ELD data, zero for - * invalid ELD, or a negative error code. - * - * The return size is the total bytes required for the whole ELD bytes, - * thus it may be over @max_bytes. If it's over @max_bytes, it implies - * that only a part of ELD bytes have been fetched. - */ -int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, - bool *audio_enabled, char *buffer, int max_bytes) -{ - struct hdac_bus *bus = codec->bus; - struct drm_audio_component *acomp = bus->audio_component; - int port, pipe; - - if (!acomp || !acomp->ops || !acomp->ops->get_eld) - return -ENODEV; - - port = pin2port(codec, nid); - if (port < 0) - return -EINVAL; - - pipe = dev_id; - return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled, - buffer, max_bytes); -} -EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); - -static int hdac_component_master_bind(struct device *dev) -{ - struct drm_audio_component *acomp = hdac_get_acomp(dev); - int ret; - - ret = component_bind_all(dev, acomp); - if (ret < 0) - return ret; - - if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power && - acomp->ops->put_power && acomp->ops->get_cdclk_freq))) { - ret = -EINVAL; - goto out_unbind; - } - - /* - * Atm, we don't support dynamic unbinding initiated by the child - * component, so pin its containing module until we unbind. - */ - if (!try_module_get(acomp->ops->owner)) { - ret = -ENODEV; - goto out_unbind; - } - - return 0; - -out_unbind: - component_unbind_all(dev, acomp); - - return ret; -} - -static void hdac_component_master_unbind(struct device *dev) -{ - struct drm_audio_component *acomp = hdac_get_acomp(dev); - - module_put(acomp->ops->owner); - component_unbind_all(dev, acomp); - WARN_ON(acomp->ops || acomp->dev); -} - -static const struct component_master_ops hdac_component_master_ops = { - .bind = hdac_component_master_bind, - .unbind = hdac_component_master_unbind, -}; - -static int hdac_component_master_match(struct device *dev, void *data) -{ - /* i915 is the only supported component */ return !strcmp(dev->driver->name, "i915"); } -/** - * snd_hdac_i915_register_notifier - Register i915 audio component ops - * @bus: HDA core bus - * @aops: i915 audio component ops - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function sets the given ops to be called by the i915 graphics driver. - * - * Returns zero for success or a negative error code. - */ -int snd_hdac_i915_register_notifier(struct hdac_bus *bus, - const struct drm_audio_component_audio_ops *aops) -{ - if (!bus->audio_component) - return -ENODEV; - - bus->audio_component->audio_ops = aops; - return 0; -} -EXPORT_SYMBOL_GPL(snd_hdac_i915_register_notifier); - /* check whether intel graphics is present */ static bool i915_gfx_present(void) { @@ -368,84 +111,26 @@ static bool i915_gfx_present(void) */ int snd_hdac_i915_init(struct hdac_bus *bus) { - struct component_match *match = NULL; - struct device *dev = bus->dev; - struct i915_audio_component *i915_acomp; struct drm_audio_component *acomp; - int ret; - - if (WARN_ON(hdac_get_acomp(dev))) - return -EBUSY; + int err; if (!i915_gfx_present()) return -ENODEV; - i915_acomp = devres_alloc(hdac_acomp_release, sizeof(*i915_acomp), - GFP_KERNEL); - if (!i915_acomp) - return -ENOMEM; - acomp = &i915_acomp->base; - bus->audio_component = acomp; - devres_add(dev, acomp); - - component_match_add(dev, &match, hdac_component_master_match, bus); - ret = component_master_add_with_match(dev, &hdac_component_master_ops, - match); - if (ret < 0) - goto out_err; - - /* - * Atm, we don't support deferring the component binding, so make sure - * i915 is loaded and that the binding successfully completes. - */ - request_module("i915"); - + err = snd_hdac_acomp_init(bus, NULL, + i915_component_master_match, + sizeof(struct i915_audio_component) - sizeof(*acomp)); + if (err < 0) + return err; + acomp = bus->audio_component; + if (!acomp) + return -ENODEV; + if (!acomp->ops) + request_module("i915"); if (!acomp->ops) { - ret = -ENODEV; - goto out_master_del; + snd_hdac_acomp_exit(bus); + return -ENODEV; } - dev_dbg(dev, "bound to i915 component master\n"); - return 0; -out_master_del: - component_master_del(dev, &hdac_component_master_ops); -out_err: - bus->audio_component = NULL; - devres_destroy(dev, hdac_acomp_release, NULL, NULL); - dev_info(dev, "failed to add i915 component master (%d)\n", ret); - - return ret; } EXPORT_SYMBOL_GPL(snd_hdac_i915_init); - -/** - * snd_hdac_i915_exit - Finalize i915 audio component - * @bus: HDA core bus - * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with i915 graphics. - * - * This function releases the i915 audio component that has been used. - * - * Returns zero for success or a negative error code. - */ -int snd_hdac_i915_exit(struct hdac_bus *bus) -{ - struct device *dev = bus->dev; - struct drm_audio_component *acomp = bus->audio_component; - - if (!acomp) - return 0; - - WARN_ON(bus->drm_power_refcount); - if (bus->drm_power_refcount > 0 && acomp->ops) - acomp->ops->put_power(acomp->dev); - - component_master_del(dev, &hdac_component_master_ops); - - bus->audio_component = NULL; - devres_destroy(dev, hdac_acomp_release, NULL, NULL); - - return 0; -} -EXPORT_SYMBOL_GPL(snd_hdac_i915_exit); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index bf174a013f2d..1de5491fb9bf 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -183,7 +183,7 @@ struct hdmi_spec { hda_nid_t vendor_nid; }; -#ifdef CONFIG_SND_HDA_I915 +#ifdef CONFIG_SND_HDA_COMPONENT static inline bool codec_has_acomp(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; @@ -2288,7 +2288,7 @@ static void generic_hdmi_free(struct hda_codec *codec) int pin_idx, pcm_idx; if (codec_has_acomp(codec)) - snd_hdac_i915_register_notifier(&codec->bus->core, NULL); + snd_hdac_acomp_register_notifier(&codec->bus->core, NULL); for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); @@ -2471,6 +2471,38 @@ static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg, snd_hda_codec_set_power_to_all(codec, fg, power_state); } +/* There is a fixed mapping between audio pin node and display port. + * on SNB, IVY, HSW, BSW, SKL, BXT, KBL: + * Pin Widget 5 - PORT B (port = 1 in i915 driver) + * Pin Widget 6 - PORT C (port = 2 in i915 driver) + * Pin Widget 7 - PORT D (port = 3 in i915 driver) + * + * on VLV, ILK: + * Pin Widget 4 - PORT B (port = 1 in i915 driver) + * Pin Widget 5 - PORT C (port = 2 in i915 driver) + * Pin Widget 6 - PORT D (port = 3 in i915 driver) + */ +static int intel_base_nid(struct hda_codec *codec) +{ + switch (codec->core.vendor_id) { + case 0x80860054: /* ILK */ + case 0x80862804: /* ILK */ + case 0x80862882: /* VLV */ + return 4; + default: + return 5; + } +} + +static int intel_pin2port(void *audio_ptr, int pin_nid) +{ + int base_nid = intel_base_nid(audio_ptr); + + if (WARN_ON(pin_nid < base_nid || pin_nid >= base_nid + 3)) + return -1; + return pin_nid - base_nid + 1; /* intel port is 1-based */ +} + static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) { struct hda_codec *codec = audio_ptr; @@ -2481,16 +2513,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) if (port < 1 || port > 3) return; - switch (codec->core.vendor_id) { - case 0x80860054: /* ILK */ - case 0x80862804: /* ILK */ - case 0x80862882: /* VLV */ - pin_nid = port + 0x03; - break; - default: - pin_nid = port + 0x04; - break; - } + pin_nid = port + intel_base_nid(codec) - 1; /* intel port is 1-based */ /* skip notification during system suspend (but not in runtime PM); * the state will be updated at resume @@ -2517,8 +2540,9 @@ static void register_i915_notifier(struct hda_codec *codec) * We need make sure audio_ptr is really setup */ wmb(); + spec->drm_audio_ops.pin2port = intel_pin2port; spec->drm_audio_ops.pin_eld_notify = intel_pin_eld_notify; - snd_hdac_i915_register_notifier(&codec->bus->core, + snd_hdac_acomp_register_notifier(&codec->bus->core, &spec->drm_audio_ops); } diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 2b7c33db4ded..4748a9d5de3b 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1530,6 +1530,11 @@ free_widgets: return ret; } +static int hdac_hdmi_pin2port(void *aptr, int pin) +{ + return pin - 4; /* map NID 0x05 -> port #1 */ +} + static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) { struct hdac_device *hdev = aptr; @@ -1584,6 +1589,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) } static struct drm_audio_component_audio_ops aops = { + .pin2port = hdac_hdmi_pin2port, .pin_eld_notify = hdac_hdmi_eld_notify_cb, }; @@ -1812,7 +1818,7 @@ static int hdmi_codec_probe(struct snd_soc_component *component) return ret; aops.audio_ptr = hdev; - ret = snd_hdac_i915_register_notifier(hdev->bus, &aops); + ret = snd_hdac_acomp_register_notifier(hdev->bus, &aops); if (ret < 0) { dev_err(&hdev->dev, "notifier register failed: err: %d\n", ret); return ret; -- cgit v1.2.3 From fa84cf094ef9667e2b91c104b0a788fd1896f482 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 18 Jul 2018 07:40:53 +0200 Subject: ALSA: pcm: Nuke snd_pcm_lib_mmap_vmalloc() snd_pcm_lib_mmap_vmalloc() was supposed to be implemented with somewhat special for vmalloc handling, but in the end, this turned to just the default handler, i.e. NULL. As the situation has never changed over decades, let's rip it off. Reviewed-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- drivers/staging/most/sound/sound.c | 1 - include/sound/pcm.h | 2 -- sound/drivers/aloop.c | 1 - sound/drivers/vx/vx_pcm.c | 2 -- sound/firewire/bebob/bebob_pcm.c | 1 - sound/firewire/dice/dice-pcm.c | 2 -- sound/firewire/digi00x/digi00x-pcm.c | 1 - sound/firewire/fireface/ff-pcm.c | 1 - sound/firewire/fireworks/fireworks_pcm.c | 1 - sound/firewire/isight.c | 1 - sound/firewire/motu/motu-pcm.c | 2 -- sound/firewire/oxfw/oxfw-pcm.c | 2 -- sound/firewire/tascam/tascam-pcm.c | 1 - sound/mips/sgio2audio.c | 3 --- sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | 1 - sound/soc/codecs/rt5514-spi.c | 1 - sound/usb/6fire/pcm.c | 1 - sound/usb/caiaq/audio.c | 1 - sound/usb/hiface/pcm.c | 1 - sound/usb/misc/ua101.c | 2 -- sound/usb/pcm.c | 2 -- 21 files changed, 30 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 04c18323c2ea..89b02fc305b8 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -457,7 +457,6 @@ static const struct snd_pcm_ops pcm_ops = { .trigger = pcm_trigger, .pointer = pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static int split_arg_list(char *buf, char **card_name, u16 *ch_num, diff --git a/include/sound/pcm.h b/include/sound/pcm.h index fcdf358a25f0..1206045ccf03 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1342,8 +1342,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_s #define snd_pcm_lib_mmap_iomem NULL #endif -#define snd_pcm_lib_mmap_vmalloc NULL - /** * snd_pcm_limit_isa_dma_size - Get the max size fitting with ISA DMA transfer * @dma: DMA number diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 78a2fdc38531..1e34e6381baa 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -778,7 +778,6 @@ static const struct snd_pcm_ops loopback_pcm_ops = { .trigger = loopback_trigger, .pointer = loopback_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static int loopback_pcm_new(struct loopback *loopback, diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index 380a028469c4..ba80f459bdc5 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -883,7 +883,6 @@ static const struct snd_pcm_ops vx_pcm_playback_ops = { .trigger = vx_pcm_trigger, .pointer = vx_pcm_playback_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; @@ -1105,7 +1104,6 @@ static const struct snd_pcm_ops vx_pcm_capture_ops = { .trigger = vx_pcm_trigger, .pointer = vx_pcm_capture_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index e6adab3ef42e..ea9b86450580 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -373,7 +373,6 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 80351b29fe0d..bb3ef5ff3488 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -412,7 +412,6 @@ int snd_dice_create_pcm(struct snd_dice *dice) .pointer = capture_pointer, .ack = capture_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops playback_ops = { .open = pcm_open, @@ -425,7 +424,6 @@ int snd_dice_create_pcm(struct snd_dice *dice) .pointer = playback_pointer, .ack = playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; unsigned int capture, playback; diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index 796f4b4645f5..fdcff0460c53 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c @@ -352,7 +352,6 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c index e3c16308363d..bf47f9ec8703 100644 --- a/sound/firewire/fireface/ff-pcm.c +++ b/sound/firewire/fireface/ff-pcm.c @@ -383,7 +383,6 @@ int snd_ff_create_pcm_devices(struct snd_ff *ff) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index 40faed5e6968..aed566d82726 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -397,7 +397,6 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 3919e186a30b..30957477e005 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -454,7 +454,6 @@ static int isight_create_pcm(struct isight *isight) .trigger = isight_trigger, .pointer = isight_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index 4330220890e8..ab69d7e6ac05 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -363,7 +363,6 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu) .pointer = capture_pointer, .ack = capture_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops playback_ops = { .open = pcm_open, @@ -376,7 +375,6 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu) .pointer = playback_pointer, .ack = playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index 3dd46285c0e2..b3f6503dd34d 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -389,7 +389,6 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) .pointer = pcm_capture_pointer, .ack = pcm_capture_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops playback_ops = { .open = pcm_open, @@ -402,7 +401,6 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; unsigned int cap = 0; diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index 6ec8ec634d4d..e4cc8990e195 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -279,7 +279,6 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) .pointer = pcm_playback_pointer, .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; struct snd_pcm *pcm; int err; diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 9fb68b35de5a..3ec9391a4736 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -685,7 +685,6 @@ static const struct snd_pcm_ops snd_sgio2audio_playback1_ops = { .trigger = snd_sgio2audio_pcm_trigger, .pointer = snd_sgio2audio_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops snd_sgio2audio_playback2_ops = { @@ -698,7 +697,6 @@ static const struct snd_pcm_ops snd_sgio2audio_playback2_ops = { .trigger = snd_sgio2audio_pcm_trigger, .pointer = snd_sgio2audio_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops snd_sgio2audio_capture_ops = { @@ -711,7 +709,6 @@ static const struct snd_pcm_ops snd_sgio2audio_capture_ops = { .trigger = snd_sgio2audio_pcm_trigger, .pointer = snd_sgio2audio_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; /* diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 4a2354b5ae00..98a6863e933c 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -276,7 +276,6 @@ static const struct snd_pcm_ops pdacf_pcm_capture_ops = { .trigger = pdacf_pcm_trigger, .pointer = pdacf_pcm_capture_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c index 18686ffb0cd5..6478d10c4f4a 100644 --- a/sound/soc/codecs/rt5514-spi.c +++ b/sound/soc/codecs/rt5514-spi.c @@ -268,7 +268,6 @@ static const struct snd_pcm_ops rt5514_spi_pcm_ops = { .hw_params = rt5514_spi_hw_params, .hw_free = rt5514_spi_hw_free, .pointer = rt5514_spi_pcm_pointer, - .mmap = snd_pcm_lib_mmap_vmalloc, .page = snd_pcm_lib_get_vmalloc_page, }; diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index 2dd2518a71d3..f8ef3e2a8ca0 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -565,7 +565,6 @@ static const struct snd_pcm_ops pcm_ops = { .trigger = usb6fire_pcm_trigger, .pointer = usb6fire_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static void usb6fire_pcm_init_urb(struct pcm_urb *urb, diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 15344d39a6cd..c6108a3d7f8f 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -348,7 +348,6 @@ static const struct snd_pcm_ops snd_usb_caiaq_ops = { .trigger = snd_usb_caiaq_pcm_trigger, .pointer = snd_usb_caiaq_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static void check_for_elapsed_periods(struct snd_usb_caiaqdev *cdev, diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c index 396c317115b1..e1fbb9cc9ea7 100644 --- a/sound/usb/hiface/pcm.c +++ b/sound/usb/hiface/pcm.c @@ -523,7 +523,6 @@ static const struct snd_pcm_ops pcm_ops = { .trigger = hiface_pcm_trigger, .pointer = hiface_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static int hiface_pcm_init_urb(struct pcm_urb *urb, diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 386fbfd5c617..a0b6d039017f 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -900,7 +900,6 @@ static const struct snd_pcm_ops capture_pcm_ops = { .trigger = capture_pcm_trigger, .pointer = capture_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops playback_pcm_ops = { @@ -913,7 +912,6 @@ static const struct snd_pcm_ops playback_pcm_ops = { .trigger = playback_pcm_trigger, .pointer = playback_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct uac_format_type_i_discrete_descriptor * diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 160f52c4871b..4b930fa47277 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1694,7 +1694,6 @@ static const struct snd_pcm_ops snd_usb_playback_ops = { .trigger = snd_usb_substream_playback_trigger, .pointer = snd_usb_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops snd_usb_capture_ops = { @@ -1707,7 +1706,6 @@ static const struct snd_pcm_ops snd_usb_capture_ops = { .trigger = snd_usb_substream_capture_trigger, .pointer = snd_usb_pcm_pointer, .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, }; static const struct snd_pcm_ops snd_usb_playback_dev_ops = { -- cgit v1.2.3