diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /sound/soc/blackfin/bf5xx-sport.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'sound/soc/blackfin/bf5xx-sport.c')
-rw-r--r-- | sound/soc/blackfin/bf5xx-sport.c | 159 |
1 files changed, 119 insertions, 40 deletions
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c index 99051ff0954e..a2d40349fcc4 100644 --- a/sound/soc/blackfin/bf5xx-sport.c +++ b/sound/soc/blackfin/bf5xx-sport.c | |||
@@ -42,8 +42,6 @@ | |||
42 | /* delay between frame sync pulse and first data bit in multichannel mode */ | 42 | /* delay between frame sync pulse and first data bit in multichannel mode */ |
43 | #define FRAME_DELAY (1<<12) | 43 | #define FRAME_DELAY (1<<12) |
44 | 44 | ||
45 | struct sport_device *sport_handle; | ||
46 | EXPORT_SYMBOL(sport_handle); | ||
47 | /* note: multichannel is in units of 8 channels, | 45 | /* note: multichannel is in units of 8 channels, |
48 | * tdm_count is # channels NOT / 8 ! */ | 46 | * tdm_count is # channels NOT / 8 ! */ |
49 | int sport_set_multichannel(struct sport_device *sport, | 47 | int sport_set_multichannel(struct sport_device *sport, |
@@ -798,86 +796,164 @@ int sport_set_err_callback(struct sport_device *sport, | |||
798 | } | 796 | } |
799 | EXPORT_SYMBOL(sport_set_err_callback); | 797 | EXPORT_SYMBOL(sport_set_err_callback); |
800 | 798 | ||
801 | struct sport_device *sport_init(struct sport_param *param, unsigned wdsize, | 799 | static int sport_config_pdev(struct platform_device *pdev, struct sport_param *param) |
802 | unsigned dummy_count, void *private_data) | ||
803 | { | 800 | { |
804 | int ret; | 801 | /* Extract settings from platform data */ |
802 | struct device *dev = &pdev->dev; | ||
803 | struct bfin_snd_platform_data *pdata = dev->platform_data; | ||
804 | struct resource *res; | ||
805 | |||
806 | param->num = pdev->id; | ||
807 | |||
808 | if (!pdata) { | ||
809 | dev_err(dev, "no platform_data\n"); | ||
810 | return -ENODEV; | ||
811 | } | ||
812 | param->pin_req = pdata->pin_req; | ||
813 | |||
814 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
815 | if (!res) { | ||
816 | dev_err(dev, "no MEM resource\n"); | ||
817 | return -ENODEV; | ||
818 | } | ||
819 | param->regs = (struct sport_register *)res->start; | ||
820 | |||
821 | /* first RX, then TX */ | ||
822 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
823 | if (!res) { | ||
824 | dev_err(dev, "no rx DMA resource\n"); | ||
825 | return -ENODEV; | ||
826 | } | ||
827 | param->dma_rx_chan = res->start; | ||
828 | |||
829 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
830 | if (!res) { | ||
831 | dev_err(dev, "no tx DMA resource\n"); | ||
832 | return -ENODEV; | ||
833 | } | ||
834 | param->dma_tx_chan = res->start; | ||
835 | |||
836 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
837 | if (!res) { | ||
838 | dev_err(dev, "no irq resource\n"); | ||
839 | return -ENODEV; | ||
840 | } | ||
841 | param->err_irq = res->start; | ||
842 | |||
843 | return 0; | ||
844 | } | ||
845 | |||
846 | struct sport_device *sport_init(struct platform_device *pdev, | ||
847 | unsigned int wdsize, unsigned int dummy_count, size_t priv_size) | ||
848 | { | ||
849 | struct device *dev = &pdev->dev; | ||
850 | struct sport_param param; | ||
805 | struct sport_device *sport; | 851 | struct sport_device *sport; |
806 | pr_debug("%s enter\n", __func__); | 852 | int ret; |
807 | BUG_ON(param == NULL); | 853 | |
808 | BUG_ON(wdsize == 0 || dummy_count == 0); | 854 | dev_dbg(dev, "%s enter\n", __func__); |
809 | sport = kmalloc(sizeof(struct sport_device), GFP_KERNEL); | 855 | |
810 | if (!sport) { | 856 | param.wdsize = wdsize; |
811 | pr_err("Failed to allocate for sport device\n"); | 857 | param.dummy_count = dummy_count; |
858 | BUG_ON(param.wdsize == 0 || param.dummy_count == 0); | ||
859 | |||
860 | ret = sport_config_pdev(pdev, ¶m); | ||
861 | if (ret) | ||
862 | return NULL; | ||
863 | |||
864 | if (peripheral_request_list(param.pin_req, "soc-audio")) { | ||
865 | dev_err(dev, "requesting Peripherals failed\n"); | ||
812 | return NULL; | 866 | return NULL; |
813 | } | 867 | } |
814 | 868 | ||
815 | memset(sport, 0, sizeof(struct sport_device)); | 869 | sport = kzalloc(sizeof(*sport), GFP_KERNEL); |
816 | sport->dma_rx_chan = param->dma_rx_chan; | 870 | if (!sport) { |
817 | sport->dma_tx_chan = param->dma_tx_chan; | 871 | dev_err(dev, "failed to allocate for sport device\n"); |
818 | sport->err_irq = param->err_irq; | 872 | goto __init_err0; |
819 | sport->regs = param->regs; | 873 | } |
820 | sport->private_data = private_data; | 874 | |
875 | sport->num = param.num; | ||
876 | sport->dma_rx_chan = param.dma_rx_chan; | ||
877 | sport->dma_tx_chan = param.dma_tx_chan; | ||
878 | sport->err_irq = param.err_irq; | ||
879 | sport->regs = param.regs; | ||
880 | sport->pin_req = param.pin_req; | ||
821 | 881 | ||
822 | if (request_dma(sport->dma_rx_chan, "SPORT RX Data") == -EBUSY) { | 882 | if (request_dma(sport->dma_rx_chan, "SPORT RX Data") == -EBUSY) { |
823 | pr_err("Failed to request RX dma %d\n", \ | 883 | dev_err(dev, "failed to request RX dma %d\n", sport->dma_rx_chan); |
824 | sport->dma_rx_chan); | ||
825 | goto __init_err1; | 884 | goto __init_err1; |
826 | } | 885 | } |
827 | if (set_dma_callback(sport->dma_rx_chan, rx_handler, sport) != 0) { | 886 | if (set_dma_callback(sport->dma_rx_chan, rx_handler, sport) != 0) { |
828 | pr_err("Failed to request RX irq %d\n", \ | 887 | dev_err(dev, "failed to request RX irq %d\n", sport->dma_rx_chan); |
829 | sport->dma_rx_chan); | ||
830 | goto __init_err2; | 888 | goto __init_err2; |
831 | } | 889 | } |
832 | 890 | ||
833 | if (request_dma(sport->dma_tx_chan, "SPORT TX Data") == -EBUSY) { | 891 | if (request_dma(sport->dma_tx_chan, "SPORT TX Data") == -EBUSY) { |
834 | pr_err("Failed to request TX dma %d\n", \ | 892 | dev_err(dev, "failed to request TX dma %d\n", sport->dma_tx_chan); |
835 | sport->dma_tx_chan); | ||
836 | goto __init_err2; | 893 | goto __init_err2; |
837 | } | 894 | } |
838 | 895 | ||
839 | if (set_dma_callback(sport->dma_tx_chan, tx_handler, sport) != 0) { | 896 | if (set_dma_callback(sport->dma_tx_chan, tx_handler, sport) != 0) { |
840 | pr_err("Failed to request TX irq %d\n", \ | 897 | dev_err(dev, "failed to request TX irq %d\n", sport->dma_tx_chan); |
841 | sport->dma_tx_chan); | ||
842 | goto __init_err3; | 898 | goto __init_err3; |
843 | } | 899 | } |
844 | 900 | ||
845 | if (request_irq(sport->err_irq, err_handler, IRQF_SHARED, "SPORT err", | 901 | if (request_irq(sport->err_irq, err_handler, IRQF_SHARED, "SPORT err", |
846 | sport) < 0) { | 902 | sport) < 0) { |
847 | pr_err("Failed to request err irq:%d\n", \ | 903 | dev_err(dev, "failed to request err irq %d\n", sport->err_irq); |
848 | sport->err_irq); | ||
849 | goto __init_err3; | 904 | goto __init_err3; |
850 | } | 905 | } |
851 | 906 | ||
852 | pr_err("dma rx:%d tx:%d, err irq:%d, regs:%p\n", | 907 | dev_info(dev, "dma rx:%d tx:%d, err irq:%d, regs:%p\n", |
853 | sport->dma_rx_chan, sport->dma_tx_chan, | 908 | sport->dma_rx_chan, sport->dma_tx_chan, |
854 | sport->err_irq, sport->regs); | 909 | sport->err_irq, sport->regs); |
855 | 910 | ||
856 | sport->wdsize = wdsize; | 911 | sport->wdsize = param.wdsize; |
857 | sport->dummy_count = dummy_count; | 912 | sport->dummy_count = param.dummy_count; |
913 | |||
914 | sport->private_data = kzalloc(priv_size, GFP_KERNEL); | ||
915 | if (!sport->private_data) { | ||
916 | dev_err(dev, "could not alloc priv data %zu bytes\n", priv_size); | ||
917 | goto __init_err4; | ||
918 | } | ||
858 | 919 | ||
859 | if (L1_DATA_A_LENGTH) | 920 | if (L1_DATA_A_LENGTH) |
860 | sport->dummy_buf = l1_data_sram_zalloc(dummy_count * 2); | 921 | sport->dummy_buf = l1_data_sram_zalloc(param.dummy_count * 2); |
861 | else | 922 | else |
862 | sport->dummy_buf = kzalloc(dummy_count * 2, GFP_KERNEL); | 923 | sport->dummy_buf = kzalloc(param.dummy_count * 2, GFP_KERNEL); |
863 | if (sport->dummy_buf == NULL) { | 924 | if (sport->dummy_buf == NULL) { |
864 | pr_err("Failed to allocate dummy buffer\n"); | 925 | dev_err(dev, "failed to allocate dummy buffer\n"); |
865 | goto __error; | 926 | goto __error1; |
866 | } | 927 | } |
867 | 928 | ||
868 | ret = sport_config_rx_dummy(sport); | 929 | ret = sport_config_rx_dummy(sport); |
869 | if (ret) { | 930 | if (ret) { |
870 | pr_err("Failed to config rx dummy ring\n"); | 931 | dev_err(dev, "failed to config rx dummy ring\n"); |
871 | goto __error; | 932 | goto __error2; |
872 | } | 933 | } |
873 | ret = sport_config_tx_dummy(sport); | 934 | ret = sport_config_tx_dummy(sport); |
874 | if (ret) { | 935 | if (ret) { |
875 | pr_err("Failed to config tx dummy ring\n"); | 936 | dev_err(dev, "failed to config tx dummy ring\n"); |
876 | goto __error; | 937 | goto __error3; |
877 | } | 938 | } |
878 | 939 | ||
940 | platform_set_drvdata(pdev, sport); | ||
941 | |||
879 | return sport; | 942 | return sport; |
880 | __error: | 943 | __error3: |
944 | if (L1_DATA_A_LENGTH) | ||
945 | l1_data_sram_free(sport->dummy_rx_desc); | ||
946 | else | ||
947 | dma_free_coherent(NULL, 2*sizeof(struct dmasg), | ||
948 | sport->dummy_rx_desc, 0); | ||
949 | __error2: | ||
950 | if (L1_DATA_A_LENGTH) | ||
951 | l1_data_sram_free(sport->dummy_buf); | ||
952 | else | ||
953 | kfree(sport->dummy_buf); | ||
954 | __error1: | ||
955 | kfree(sport->private_data); | ||
956 | __init_err4: | ||
881 | free_irq(sport->err_irq, sport); | 957 | free_irq(sport->err_irq, sport); |
882 | __init_err3: | 958 | __init_err3: |
883 | free_dma(sport->dma_tx_chan); | 959 | free_dma(sport->dma_tx_chan); |
@@ -885,6 +961,8 @@ __init_err2: | |||
885 | free_dma(sport->dma_rx_chan); | 961 | free_dma(sport->dma_rx_chan); |
886 | __init_err1: | 962 | __init_err1: |
887 | kfree(sport); | 963 | kfree(sport); |
964 | __init_err0: | ||
965 | peripheral_free_list(param.pin_req); | ||
888 | return NULL; | 966 | return NULL; |
889 | } | 967 | } |
890 | EXPORT_SYMBOL(sport_init); | 968 | EXPORT_SYMBOL(sport_init); |
@@ -917,8 +995,9 @@ void sport_done(struct sport_device *sport) | |||
917 | free_dma(sport->dma_tx_chan); | 995 | free_dma(sport->dma_tx_chan); |
918 | free_irq(sport->err_irq, sport); | 996 | free_irq(sport->err_irq, sport); |
919 | 997 | ||
998 | kfree(sport->private_data); | ||
999 | peripheral_free_list(sport->pin_req); | ||
920 | kfree(sport); | 1000 | kfree(sport); |
921 | sport = NULL; | ||
922 | } | 1001 | } |
923 | EXPORT_SYMBOL(sport_done); | 1002 | EXPORT_SYMBOL(sport_done); |
924 | 1003 | ||