Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i2c: tda998x: Improve tda998x_configure_audio() audio related pdata

Define struct tda998x_audio_params in include/drm/i2c/tda998x.h and
use it in pdata and for tda998x_configure_audio() parameters. Also
updates tda998x_write_aif() to take struct hdmi_audio_infoframe *
directly as a parameter.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

authored by

Jyri Sarha and committed by
Russell King
95db3b25 3ef500a5

+64 -48
+46 -38
drivers/gpu/drm/i2c/tda998x_drv.c
··· 41 41 u8 vip_cntrl_0; 42 42 u8 vip_cntrl_1; 43 43 u8 vip_cntrl_2; 44 - struct tda998x_encoder_params params; 44 + struct tda998x_audio_params audio_params; 45 45 46 46 wait_queue_head_t wq_edid; 47 47 volatile int wq_edid_wait; ··· 666 666 reg_set(priv, REG_DIP_IF_FLAGS, bit); 667 667 } 668 668 669 - static void 670 - tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p) 669 + static int tda998x_write_aif(struct tda998x_priv *priv, 670 + struct hdmi_audio_infoframe *cea) 671 671 { 672 672 union hdmi_infoframe frame; 673 673 674 - hdmi_audio_infoframe_init(&frame.audio); 675 - 676 - frame.audio.channels = p->audio_frame[1] & 0x07; 677 - frame.audio.channel_allocation = p->audio_frame[4]; 678 - frame.audio.level_shift_value = (p->audio_frame[5] & 0x78) >> 3; 679 - frame.audio.downmix_inhibit = (p->audio_frame[5] & 0x80) >> 7; 680 - 681 - /* 682 - * L-PCM and IEC61937 compressed audio shall always set sample 683 - * frequency to "refer to stream". For others, see the HDMI 684 - * specification. 685 - */ 686 - frame.audio.sample_frequency = (p->audio_frame[2] & 0x1c) >> 2; 674 + frame.audio = *cea; 687 675 688 676 tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, &frame); 677 + 678 + return 0; 689 679 } 690 680 691 681 static void ··· 700 710 } 701 711 } 702 712 703 - static void 713 + static int 704 714 tda998x_configure_audio(struct tda998x_priv *priv, 705 - struct drm_display_mode *mode, struct tda998x_encoder_params *p) 715 + struct tda998x_audio_params *params, 716 + unsigned mode_clock) 706 717 { 707 718 u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv; 708 719 u32 n; 709 720 710 721 /* Enable audio ports */ 711 - reg_write(priv, REG_ENA_AP, p->audio_cfg); 712 - reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg); 722 + reg_write(priv, REG_ENA_AP, params->config); 713 723 714 724 /* Set audio input source */ 715 - switch (p->audio_format) { 725 + switch (params->format) { 716 726 case AFMT_SPDIF: 727 + reg_write(priv, REG_ENA_ACLK, 0); 717 728 reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF); 718 729 clksel_aip = AIP_CLKSEL_AIP_SPDIF; 719 730 clksel_fs = AIP_CLKSEL_FS_FS64SPDIF; ··· 722 731 break; 723 732 724 733 case AFMT_I2S: 734 + reg_write(priv, REG_ENA_ACLK, 1); 725 735 reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S); 726 736 clksel_aip = AIP_CLKSEL_AIP_I2S; 727 737 clksel_fs = AIP_CLKSEL_FS_ACLK; 728 - cts_n = CTS_N_M(3) | CTS_N_K(3); 738 + switch (params->sample_width) { 739 + case 16: 740 + cts_n = CTS_N_M(3) | CTS_N_K(1); 741 + break; 742 + case 18: 743 + case 20: 744 + case 24: 745 + cts_n = CTS_N_M(3) | CTS_N_K(2); 746 + break; 747 + default: 748 + case 32: 749 + cts_n = CTS_N_M(3) | CTS_N_K(3); 750 + break; 751 + } 729 752 break; 730 753 731 754 default: 732 755 BUG(); 733 - return; 756 + return -EINVAL; 734 757 } 735 758 736 759 reg_write(priv, REG_AIP_CLKSEL, clksel_aip); ··· 760 755 * assume 100MHz requires larger divider. 761 756 */ 762 757 adiv = AUDIO_DIV_SERCLK_8; 763 - if (mode->clock > 100000) 758 + if (mode_clock > 100000) 764 759 adiv++; /* AUDIO_DIV_SERCLK_16 */ 765 760 766 761 /* S/PDIF asks for a larger divider */ 767 - if (p->audio_format == AFMT_SPDIF) 762 + if (params->format == AFMT_SPDIF) 768 763 adiv++; /* AUDIO_DIV_SERCLK_16 or _32 */ 769 764 770 765 reg_write(priv, REG_AUDIO_DIV, adiv); ··· 773 768 * This is the approximate value of N, which happens to be 774 769 * the recommended values for non-coherent clocks. 775 770 */ 776 - n = 128 * p->audio_sample_rate / 1000; 771 + n = 128 * params->sample_rate / 1000; 777 772 778 773 /* Write the CTS and N values */ 779 774 buf[0] = 0x44; ··· 791 786 reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS); 792 787 reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS); 793 788 794 - /* Write the channel status */ 795 - buf[0] = IEC958_AES0_CON_NOT_COPYRIGHT; 796 - buf[1] = 0x00; 797 - buf[2] = IEC958_AES3_CON_FS_NOTID; 798 - buf[3] = IEC958_AES4_CON_ORIGFS_NOTID | 799 - IEC958_AES4_CON_MAX_WORDLEN_24; 789 + /* Write the channel status 790 + * The REG_CH_STAT_B-registers skip IEC958 AES2 byte, because 791 + * there is a separate register for each I2S wire. 792 + */ 793 + buf[0] = params->status[0]; 794 + buf[1] = params->status[1]; 795 + buf[2] = params->status[3]; 796 + buf[3] = params->status[4]; 800 797 reg_write_range(priv, REG_CH_STAT_B(0), buf, 4); 801 798 802 799 tda998x_audio_mute(priv, true); 803 800 msleep(20); 804 801 tda998x_audio_mute(priv, false); 805 802 806 - /* Write the audio information packet */ 807 - tda998x_write_aif(priv, p); 803 + return tda998x_write_aif(priv, &params->cea); 808 804 } 809 805 810 806 /* DRM encoder functions */ ··· 826 820 VIP_CNTRL_2_SWAP_F(p->swap_f) | 827 821 (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0); 828 822 829 - priv->params = *p; 823 + priv->audio_params = p->audio_params; 830 824 } 831 825 832 826 static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode) ··· 1063 1057 1064 1058 tda998x_write_avi(priv, adjusted_mode); 1065 1059 1066 - if (priv->params.audio_cfg) 1067 - tda998x_configure_audio(priv, adjusted_mode, 1068 - &priv->params); 1060 + if (priv->audio_params.format != AFMT_UNUSED) { 1061 + tda998x_configure_audio(priv, 1062 + &priv->audio_params, 1063 + adjusted_mode->clock); 1064 + } 1069 1065 } 1070 1066 } 1071 1067
+18 -10
include/drm/i2c/tda998x.h
··· 1 1 #ifndef __DRM_I2C_TDA998X_H__ 2 2 #define __DRM_I2C_TDA998X_H__ 3 3 4 + #include <linux/hdmi.h> 5 + 6 + enum { 7 + AFMT_UNUSED = 0, 8 + AFMT_SPDIF = 1, 9 + AFMT_I2S = 2, 10 + }; 11 + 12 + struct tda998x_audio_params { 13 + u8 config; 14 + u8 format; 15 + unsigned sample_width; 16 + unsigned sample_rate; 17 + struct hdmi_audio_infoframe cea; 18 + u8 status[5]; 19 + }; 20 + 4 21 struct tda998x_encoder_params { 5 22 u8 swap_b:3; 6 23 u8 mirr_b:1; ··· 32 15 u8 swap_e:3; 33 16 u8 mirr_e:1; 34 17 35 - u8 audio_cfg; 36 - u8 audio_clk_cfg; 37 - u8 audio_frame[6]; 38 - 39 - enum { 40 - AFMT_SPDIF, 41 - AFMT_I2S 42 - } audio_format; 43 - 44 - unsigned audio_sample_rate; 18 + struct tda998x_audio_params audio_params; 45 19 }; 46 20 47 21 #endif