/* K8 systems have some devices (typically in the builtin northbridge) that are only accessible using type1 Normally this can be expressed in the MCFG by not listing them and assigning suitable _SEGs, but this isn't implemented in some BIOS. Instead try to discover all devices on bus 0 that are unreachable using MM and fallback for them. */ static __init void unreachable_devices(void) { int i, k; unsigned long flags; for (k = 0; k < MAX_CHECK_BUS; k++) { for (i = 0; i < 32; i++) { u32 val1; u32 addr; pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1); if (val1 == 0xffffffff) continue; /* Locking probably not needed, but safer */ spin_lock_irqsave(&pci_config_lock, flags); addr = get_base_addr(0, k, PCI_DEVFN(i, 0)); if (addr != 0) pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0)); if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1) { set_bit(i + 32*k, fallback_slots); printk(KERN_NOTICE "PCI: No mmconfig possible on %x:%x\n", k, i); } spin_unlock_irqrestore(&pci_config_lock, flags); } } }
static void mi2s_release(struct mi2s_state *mi2s, uint8_t dev_id) { void __iomem *baddr = get_base_addr(mi2s, dev_id); if (!IS_ERR(baddr)) writel(MI2S_RESET__MI2S_RESET__ACTIVE, baddr + MI2S_RESET_OFFSET); }
static int pci_mmcfg_read(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 *value) { unsigned long flags; u32 base; if ((bus > 255) || (devfn > 255) || (reg > 4095)) { err: *value = -1; return -EINVAL; } base = get_base_addr(seg, bus, devfn); if (!base) goto err; raw_spin_lock_irqsave(&pci_config_lock, flags); pci_exp_set_dev_base(base, bus, devfn); switch (len) { case 1: *value = mmio_config_readb(mmcfg_virt_addr + reg); break; case 2: *value = mmio_config_readw(mmcfg_virt_addr + reg); break; case 4: *value = mmio_config_readl(mmcfg_virt_addr + reg); break; } raw_spin_unlock_irqrestore(&pci_config_lock, flags); return 0; }
static int pci_mmcfg_write(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 value) { unsigned long flags; u32 base; if ((bus > 255) || (devfn > 255) || (reg > 4095)) return -EINVAL; base = get_base_addr(seg, bus, devfn); if (!base) return -EINVAL; raw_spin_lock_irqsave(&pci_config_lock, flags); pci_exp_set_dev_base(base, bus, devfn); switch (len) { case 1: mmio_config_writeb(mmcfg_virt_addr + reg, value); break; case 2: mmio_config_writew(mmcfg_virt_addr + reg, value); break; case 4: mmio_config_writel(mmcfg_virt_addr + reg, value); break; } raw_spin_unlock_irqrestore(&pci_config_lock, flags); return 0; }
static void mi2s_set_output_num_channels(struct mi2s_state *mi2s, uint8_t dev_id, uint8_t channels) { void __iomem *baddr = get_base_addr(mi2s, dev_id); uint32_t val; if (!IS_ERR(baddr)) { val = readl(baddr + MI2S_TX_MODE_OFFSET); if (channels == MI2S_CHAN_MONO_RAW) { val = (val & ~(HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_BMSK | HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_P_MONO_BMSK)) | ((MI2S_TX_MODE__MI2S_TX_STEREO_MODE__MONO_SAMPLE << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_SHFT) | (MI2S_TX_MODE__MI2S_TX_CODEC_16_MONO_MODE__RAW << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_P_MONO_SHFT)); } else if (channels == MI2S_CHAN_MONO_PACKED) { val = (val & ~(HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_BMSK | HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_P_MONO_BMSK)) | ((MI2S_TX_MODE__MI2S_TX_STEREO_MODE__MONO_SAMPLE << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_SHFT) | (MI2S_TX_MODE__MI2S_TX_CODEC_16_MONO_MODE__PACKED << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_P_MONO_SHFT)); } else if (channels == MI2S_CHAN_STEREO) { val = (val & ~(HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_BMSK | HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_CH_TYPE_BMSK)) | ((MI2S_TX_MODE__MI2S_TX_STEREO_MODE__STEREO_SAMPLE << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_SHFT) | (MI2S_TX_MODE__MI2S_TX_CH_TYPE__2_CHANNEL << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_CH_TYPE_SHFT)); } else if (channels == MI2S_CHAN_4CHANNELS) { val = (val & ~(HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_BMSK | HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_CH_TYPE_BMSK)) | ((MI2S_TX_MODE__MI2S_TX_STEREO_MODE__STEREO_SAMPLE << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_SHFT) | (MI2S_TX_MODE__MI2S_TX_CH_TYPE__4_CHANNEL << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_CH_TYPE_SHFT)); } else if (channels == MI2S_CHAN_6CHANNELS) { val = (val & ~(HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_BMSK | HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_CH_TYPE_BMSK)) | ((MI2S_TX_MODE__MI2S_TX_STEREO_MODE__STEREO_SAMPLE << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_SHFT) | (MI2S_TX_MODE__MI2S_TX_CH_TYPE__6_CHANNEL << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_CH_TYPE_SHFT)); } else if (channels == MI2S_CHAN_8CHANNELS) { val = (val & ~(HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_BMSK | HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_CH_TYPE_BMSK)) | ((MI2S_TX_MODE__MI2S_TX_STEREO_MODE__STEREO_SAMPLE << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_STEREO_MODE_SHFT) | (MI2S_TX_MODE__MI2S_TX_CH_TYPE__8_CHANNEL << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_CH_TYPE_SHFT)); } writel(val, baddr + MI2S_TX_MODE_OFFSET); } }
void hp80_io_slot_device::install_read_write_handlers(address_space& space) { hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device()); if (card != nullptr) { card->install_read_write_handlers(space , get_base_addr()); } }
static void mi2s_set_sd(struct mi2s_state *mi2s, uint8_t dev_id, uint8_t sd_map) { void __iomem *baddr = get_base_addr(mi2s, dev_id); uint32_t val; if (!IS_ERR(baddr)) { val = readl(baddr + MI2S_MODE_OFFSET) & ~(MI2S_SD_N_EN_MASK | MI2S_TX_RX_N_MASK); writel(val | sd_map, baddr + MI2S_MODE_OFFSET); } }
static void mi2s_set_output_4ch_map(struct mi2s_state *mi2s, uint8_t dev_id, bool high_low) { void __iomem *baddr = get_base_addr(mi2s, dev_id); uint32_t val; if (!IS_ERR(baddr)) { val = readl(baddr + MI2S_TX_MODE_OFFSET); val = (val & ~HWIO_AUDIO1_MI2S_TX_MODE_MI2S_4_0_CH_MAP_BMSK) | (high_low << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_4_0_CH_MAP_SHFT); writel(val, baddr + MI2S_TX_MODE_OFFSET); } }
static void mi2s_set_output_clk_synch(struct mi2s_state *mi2s, uint8_t dev_id) { void __iomem *baddr = get_base_addr(mi2s, dev_id); uint32_t val; if (!IS_ERR(baddr)) { val = readl(baddr + MI2S_TX_MODE_OFFSET); writel(((val & ~HWIO_AUDIO1_MI2S_TX_MODE_MI2S_TX_DMA_ACK_SYNCH_EN_BMSK) | MI2S_TX_MODE__MI2S_TX_DMA_ACK_SYNCH_EN__SYNC_ENABLE), baddr + MI2S_TX_MODE_OFFSET); } }
static void mi2s_set_input_sd_line(struct mi2s_state *mi2s, uint8_t dev_id, uint8_t sd_line) { void __iomem *baddr = get_base_addr(mi2s, dev_id); uint32_t val; if (!IS_ERR(baddr)) { val = readl(baddr + MI2S_RX_MODE_OFFSET); if (sd_line < 4) { val = (val & ~HWIO_AUDIO1_MI2S_RX_MODE_MI2S_RX_I2S_LINE_BMSK) | (sd_line << HWIO_AUDIO1_MI2S_RX_MODE_MI2S_RX_I2S_LINE_SHFT); writel(val, baddr + MI2S_RX_MODE_OFFSET); } } }
static void mi2s_set_output_2ch_map(struct mi2s_state *mi2s, uint8_t dev_id, uint8_t sd_line) { void __iomem *baddr = get_base_addr(mi2s, dev_id); uint32_t val; if (!IS_ERR(baddr)) { val = readl(baddr + MI2S_TX_MODE_OFFSET); if (sd_line < 4) { val = (val & ~HWIO_AUDIO1_MI2S_TX_MODE_MI2S_2_0_CH_MAP_BMSK) | (sd_line << HWIO_AUDIO1_MI2S_TX_MODE_MI2S_2_0_CH_MAP_SHFT); writel(val, baddr + MI2S_TX_MODE_OFFSET); } } }
uint8_t l_to_p(const logical_addr* logical, int* tlb_hit){ short find = 0; int i; for(i = 0; i < last_entry; i++){ if(tlb[i].page_index == logical->page_number){ tlb[i].access++; find = 1; if(tlb_hit) *tlb_hit = 1; return tlb[i].frame_index; } } if(!find){ if(tlb_hit) *tlb_hit = 0; uint8_t frame = get_base_addr(logical->page_number); add_tlb_entry(logical->page_number, frame); return frame; } return 0; }
/* Set who control aux pcm : adsp or MSM */ void aux_codec_adsp_codec_ctl_en(bool msm_adsp_en) { void __iomem *baddr = get_base_addr(&the_aux_pcm_state); uint32_t val; if (!IS_ERR(baddr)) { val = readl(baddr + AUX_CODEC_CTL_OFFSET); if (msm_adsp_en) { /* adsp */ writel( ((val & ~AUX_CODEC_CTL_ADSP_CODEC_CTL_EN_BMSK) | AUX_CODEC_CTL__ADSP_CODEC_CTL_EN__ADSP_V), baddr + AUX_CODEC_CTL_OFFSET); } else { /* MSM */ writel( ((val & ~AUX_CODEC_CTL_ADSP_CODEC_CTL_EN_BMSK) | AUX_CODEC_CTL__ADSP_CODEC_CTL_EN__MSM_V), baddr + AUX_CODEC_CTL_OFFSET); } } }
static void mi2s_master(struct mi2s_state *mi2s, uint8_t dev_id, bool master) { void __iomem *baddr = get_base_addr(mi2s, dev_id); uint32_t val; if (!IS_ERR(baddr)) { val = readl(baddr + MI2S_MODE_OFFSET); if (master) { writel( ((val & ~HWIO_AUDIO1_MI2S_MODE_MI2S_MASTER_BMSK) | (MI2S_MODE__MI2S_MASTER__MASTER << HWIO_AUDIO1_MI2S_MODE_MI2S_MASTER_SHFT)), baddr + MI2S_MODE_OFFSET); } else { writel( ((val & ~HWIO_AUDIO1_MI2S_MODE_MI2S_MASTER_BMSK) | (MI2S_MODE__MI2S_MASTER__SLAVE << HWIO_AUDIO1_MI2S_MODE_MI2S_MASTER_SHFT)), baddr + MI2S_MODE_OFFSET); } } }
/* Set who control aux pcm path: adsp or MSM */ void aux_codec_pcm_path_ctl_en(bool msm_adsp_en) { void __iomem *baddr = get_base_addr(&the_aux_pcm_state); uint32_t val; if (!IS_ERR(baddr)) { val = readl(baddr + PCM_PATH_CTL_OFFSET); if (msm_adsp_en) { /* adsp */ writel( ((val & ~PCM_PATH_CTL__ADSP_CTL_EN_BMSK) | PCM_PATH_CTL__ADSP_CTL_EN__ADSP_V), baddr + PCM_PATH_CTL_OFFSET); } else { /* MSM */ writel( ((val & ~PCM_PATH_CTL__ADSP_CTL_EN_BMSK) | PCM_PATH_CTL__ADSP_CTL_EN__MSM_V), baddr + PCM_PATH_CTL_OFFSET); } } return; }
/* K8 systems have some devices (typically in the builtin northbridge) that are only accessible using type1 Normally this can be expressed in the MCFG by not listing them and assigning suitable _SEGs, but this isn't implemented in some BIOS. Instead try to discover all devices on bus 0 that are unreachable using MM and fallback for them. We only do this for bus 0/seg 0 */ static __init void unreachable_devices(void) { int i; unsigned long flags; for (i = 0; i < 32; i++) { u32 val1; u32 addr; pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1); if (val1 == 0xffffffff) continue; /* Locking probably not needed, but safer */ spin_lock_irqsave(&pci_config_lock, flags); addr = get_base_addr(0, 0, PCI_DEVFN(i, 0)); if (addr != 0) pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0)); if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1) set_bit(i, fallback_slots); spin_unlock_irqrestore(&pci_config_lock, flags); } }
static void mi2s_set_word_type(struct mi2s_state *mi2s, uint8_t dev_id, uint8_t size) { void __iomem *baddr = get_base_addr(mi2s, dev_id); uint32_t val; if (!IS_ERR(baddr)) { val = readl(baddr + MI2S_MODE_OFFSET); switch (size) { case WT_16_BIT: writel( ((val & ~HWIO_AUDIO1_MI2S_MODE_MI2S_TX_RX_WORD_TYPE_BMSK) | (MI2S_MODE__MI2S_TX_RX_WORD_TYPE__16_BIT << HWIO_AUDIO1_MI2S_MODE_MI2S_TX_RX_WORD_TYPE_SHFT)), baddr + MI2S_MODE_OFFSET); break; case WT_24_BIT: writel( ((val & ~HWIO_AUDIO1_MI2S_MODE_MI2S_TX_RX_WORD_TYPE_BMSK) | (MI2S_MODE__MI2S_TX_RX_WORD_TYPE__24_BIT << HWIO_AUDIO1_MI2S_MODE_MI2S_TX_RX_WORD_TYPE_SHFT)), baddr + MI2S_MODE_OFFSET); break; case WT_32_BIT: writel( ((val & ~HWIO_AUDIO1_MI2S_MODE_MI2S_TX_RX_WORD_TYPE_BMSK) | (MI2S_MODE__MI2S_TX_RX_WORD_TYPE__32_BIT << HWIO_AUDIO1_MI2S_MODE_MI2S_TX_RX_WORD_TYPE_SHFT)), baddr + MI2S_MODE_OFFSET); break; default: break; } } }
int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, unsigned int devfn) { return get_base_addr(seg, bus, devfn) != 0; }
bool mi2s_set_hdmi_input_path(uint8_t channels, uint8_t size, uint8_t sd_line_mask) { bool ret_val = MI2S_TRUE; struct mi2s_state *mi2s = &the_mi2s_state; u8 sd_line, num_of_sd_lines = 0; void __iomem *baddr; uint32_t val; pr_debug("%s: channels = %u size = %u sd_line_mask = 0x%x\n", __func__, channels, size, sd_line_mask); if ((channels != 1) && (channels != MAX_NUM_CHANNELS_IN)) { pr_err("%s: invalid number of channels. channels = %u\n", __func__, channels); return MI2S_FALSE; } if (size > WT_MAX) { pr_err("%s: mi2s word size can not be greater than 32 bits\n", __func__); return MI2S_FALSE; } sd_line_mask &= MI2S_SD_LINE_MASK; if (!sd_line_mask) { pr_err("%s: Did not set any data lines to use " " sd_line_mask =0x%x\n", __func__, sd_line_mask); return MI2S_FALSE; } num_of_sd_lines = num_of_bits_set(sd_line_mask); if (num_of_sd_lines != 1) { pr_err("%s: for two channel input only one SD lines is" " needed. num_of_sd_lines = %u sd_line_mask = 0x%x\n", __func__, num_of_sd_lines, sd_line_mask); return MI2S_FALSE; } /*Second argument to find_first_bit should be maximum number of bits interested*/ sd_line = find_first_bit((unsigned long *)&sd_line_mask, sizeof(sd_line_mask) * 8); pr_debug("sd_line = %d\n", sd_line); /* Ensure sd_line parameter is valid (0-max) */ if (sd_line > MAX_SD_LINES) { pr_err("%s: Line number can not be greater than = %u\n", __func__, MAX_SD_LINES); return MI2S_FALSE; } mutex_lock(&mi2s->mutex_lock); /* Put device in reset */ mi2s_reset(mi2s, HDMI); mi2s_master(mi2s, HDMI, 1); /* Set word type */ mi2s_set_word_type(mi2s, HDMI, size); /* Enable clock crossing synchronization of WR DMA ACK */ mi2s_set_input_clk_synch(mi2s, HDMI); /* Ensure channels parameter is valid (non-zero, less than max, * and even or mono) */ mi2s_set_input_num_channels(mi2s, HDMI, channels); mi2s_set_input_sd_line(mi2s, HDMI, sd_line); mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP << sd_line)); baddr = get_base_addr(mi2s, HDMI); val = readl(baddr + MI2S_MODE_OFFSET); pr_debug("%s(): MI2S_MODE = 0x%x\n", __func__, val); val = readl(baddr + MI2S_RX_MODE_OFFSET); pr_debug("%s(): MI2S_RX_MODE = 0x%x\n", __func__, val); /* Release device from reset */ mi2s_release(mi2s, HDMI); mutex_unlock(&mi2s->mutex_lock); mb(); return ret_val; }
bool mi2s_set_hdmi_output_path(uint8_t channels, uint8_t size, uint8_t sd_line_mask) { bool ret_val = MI2S_TRUE; struct mi2s_state *mi2s = &the_mi2s_state; u8 sd_line, num_of_sd_lines = 0; void __iomem *baddr; uint32_t val; pr_debug("%s: channels = %u size = %u sd_line_mask = 0x%x\n", __func__, channels, size, sd_line_mask); if ((channels == 0) || (channels > MAX_NUM_CHANNELS_OUT) || ((channels != 1) && (channels % 2 != 0))) { pr_err("%s: invalid number of channels. channels = %u\n", __func__, channels); return MI2S_FALSE; } sd_line_mask &= MI2S_SD_LINE_MASK; if (!sd_line_mask) { pr_err("%s: Did not set any data lines to use " " sd_line_mask =0x%x\n", __func__, sd_line_mask); return MI2S_FALSE; } mutex_lock(&mi2s->mutex_lock); /* Put device in reset */ mi2s_reset(mi2s, HDMI); mi2s_master(mi2s, HDMI, 1); /* Set word type */ if (size <= WT_MAX) mi2s_set_word_type(mi2s, HDMI, size); else ret_val = MI2S_FALSE; /* Enable clock crossing synchronization of RD DMA ACK */ mi2s_set_output_clk_synch(mi2s, HDMI); mi2s_set_output_num_channels(mi2s, HDMI, channels); num_of_sd_lines = num_of_bits_set(sd_line_mask); /*Second argument to find_first_bit should be maximum number of bit*/ sd_line = find_first_bit((unsigned long *)&sd_line_mask, sizeof(sd_line_mask) * 8); pr_debug("sd_line = %d\n", sd_line); if (channels == 1) { if (num_of_sd_lines != 1) { pr_err("%s: for one channel only one SD lines is" " needed. num_of_sd_lines = %u\n", __func__, num_of_sd_lines); ret_val = MI2S_FALSE; goto error; } if (sd_line != 0) { pr_err("%s: for one channel tx, need to use SD_0 " "sd_line = %u\n", __func__, sd_line); ret_val = MI2S_FALSE; goto error; } /* Enable SD line 0 for Tx (only option for * mono audio) */ mi2s_set_sd(mi2s, HDMI, MI2S_SD_0_EN_MAP | MI2S_SD_0_TX_MAP); } else if (channels == 2) { if (num_of_sd_lines != 1) { pr_err("%s: for two channel only one SD lines is" " needed. num_of_sd_lines = %u\n", __func__, num_of_sd_lines); ret_val = MI2S_FALSE; goto error; } /* Enable single SD line for Tx */ mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP << sd_line) | (MI2S_SD_0_TX_MAP << sd_line)); /* Set 2-channel mapping */ mi2s_set_output_2ch_map(mi2s, HDMI, sd_line); } else if (channels == 4) { if (num_of_sd_lines != 2) { pr_err("%s: for 4 channels two SD lines are" " needed. num_of_sd_lines = %u\\n", __func__, num_of_sd_lines); ret_val = MI2S_FALSE; goto error; } if ((sd_line_mask && MI2S_SD_0) && (sd_line_mask && MI2S_SD_1)) { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP | MI2S_SD_1_EN_MAP) | (MI2S_SD_0_TX_MAP | MI2S_SD_1_TX_MAP)); mi2s_set_output_4ch_map(mi2s, HDMI, MI2S_FALSE); } else if ((sd_line_mask && MI2S_SD_2) && (sd_line_mask && MI2S_SD_3)) { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_2_EN_MAP | MI2S_SD_3_EN_MAP) | (MI2S_SD_2_TX_MAP | MI2S_SD_3_TX_MAP)); mi2s_set_output_4ch_map(mi2s, HDMI, MI2S_TRUE); } else { pr_err("%s: for 4 channels invalid SD lines usage" " sd_line_mask = 0x%x\n", __func__, sd_line_mask); ret_val = MI2S_FALSE; goto error; } } else if (channels == 6) { if (num_of_sd_lines != 3) { pr_err("%s: for 6 channels three SD lines are" " needed. num_of_sd_lines = %u\n", __func__, num_of_sd_lines); ret_val = MI2S_FALSE; goto error; } if ((sd_line_mask && MI2S_SD_0) && (sd_line_mask && MI2S_SD_1) && (sd_line_mask && MI2S_SD_2)) { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP | MI2S_SD_1_EN_MAP | MI2S_SD_2_EN_MAP) | (MI2S_SD_0_TX_MAP | MI2S_SD_1_TX_MAP | MI2S_SD_2_TX_MAP)); } else if ((sd_line_mask && MI2S_SD_1) && (sd_line_mask && MI2S_SD_2) && (sd_line_mask && MI2S_SD_3)) { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_1_EN_MAP | MI2S_SD_2_EN_MAP | MI2S_SD_3_EN_MAP) | (MI2S_SD_1_TX_MAP | MI2S_SD_2_TX_MAP | MI2S_SD_3_TX_MAP)); } else { pr_err("%s: for 6 channels invalid SD lines usage" " sd_line_mask = 0x%x\n", __func__, sd_line_mask); ret_val = MI2S_FALSE; goto error; } } else if (channels == 8) { if (num_of_sd_lines != 4) { pr_err("%s: for 8 channels four SD lines are" " needed. num_of_sd_lines = %u\n", __func__, num_of_sd_lines); ret_val = MI2S_FALSE; goto error; } mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP | MI2S_SD_1_EN_MAP | MI2S_SD_2_EN_MAP | MI2S_SD_3_EN_MAP) | (MI2S_SD_0_TX_MAP | MI2S_SD_1_TX_MAP | MI2S_SD_2_TX_MAP | MI2S_SD_3_TX_MAP)); } else { pr_err("%s: invalid number channels = %u\n", __func__, channels); ret_val = MI2S_FALSE; goto error; } baddr = get_base_addr(mi2s, HDMI); val = readl(baddr + MI2S_MODE_OFFSET); pr_debug("%s(): MI2S_MODE = 0x%x\n", __func__, val); val = readl(baddr + MI2S_TX_MODE_OFFSET); pr_debug("%s(): MI2S_TX_MODE = 0x%x\n", __func__, val); error: /* Release device from reset */ mi2s_release(mi2s, HDMI); mutex_unlock(&mi2s->mutex_lock); mb(); return ret_val; }