Ejemplo n.º 1
0
static int sii9244_cbus_init(struct sii9244_data *sii9244)
{
	u8 value;

	cbus_write_reg(sii9244, 0x07, 0x36);
	cbus_write_reg(sii9244, 0x40, 0x03);
	cbus_write_reg(sii9244, 0x42, 0x06);
	cbus_write_reg(sii9244, 0x36, 0x0C);

	cbus_write_reg(sii9244, 0x3D, 0xFD);
	cbus_write_reg(sii9244, 0x1C, 0x00);

	cbus_write_reg(sii9244, 0x44, 0x02);

	/* Setup our devcap*/
	cbus_write_reg(sii9244, 0x80, 0x04);
	cbus_write_reg(sii9244, 0x81, 0x10);
	cbus_write_reg(sii9244, 0x82, 0x02);
	cbus_write_reg(sii9244, 0x83, 0);
	cbus_write_reg(sii9244, 0x84, 0);
	cbus_write_reg(sii9244, 0x85, 0x01 | 0x02);
	cbus_write_reg(sii9244, 0x86, 0x01);
	cbus_write_reg(sii9244, 0x87, 0);
	cbus_write_reg(sii9244, 0x88, (1<<2) | (1<<1) | (1<<3) | (1<<7));
	cbus_write_reg(sii9244, 0x89, 0x0F);
	cbus_write_reg(sii9244, 0x8A, (1<<0) | (1<<1) | (1<<2));
	cbus_write_reg(sii9244, 0x8B, 0);
	cbus_write_reg(sii9244, 0x8C, 0);
	cbus_write_reg(sii9244, 0x8D, 16);
	cbus_write_reg(sii9244, 0x8E, 0x44);
	cbus_write_reg(sii9244, 0x8F, 0);

	cbus_read_reg(sii9244, 0x31, &value);
	value |= 0x0C;
	cbus_write_reg(sii9244, 0x31, value);

	cbus_read_reg(sii9244, 0x22, &value);
	value &= 0x0F;
	cbus_write_reg(sii9244, 0x22, value);

	cbus_write_reg(sii9244, 0x30, 0x01);

	return 0;
}
Ejemplo n.º 2
0
static int cbus_set_reg(struct sii9244_data *sii9244, unsigned int offset,
		u8 mask)
{
	int ret;
	u8 value;

	ret = cbus_read_reg(sii9244, offset, &value);
	if (ret < 0)
		return ret;

	value |= mask;

	return cbus_write_reg(sii9244, offset, value);
}
Ejemplo n.º 3
0
Archivo: retu.c Proyecto: tmlind/linux
/**
 * __retu_read_reg - Read a value from a register in Retu
 * @retu: pointer to retu structure
 * @reg: the register address to read from
 */
static int __retu_read_reg(struct retu *retu, unsigned reg)
{
	return cbus_read_reg(retu->dev, retu->devid, reg);
}
Ejemplo n.º 4
0
/**
 * retu_read_reg - Read a value from a register in Retu
 * @reg: the register to read from
 *
 * This function returns the contents of the specified register
 */
int retu_read_reg(int reg)
{
	BUG_ON(!retu_initialized);
	return cbus_read_reg(cbus_host, RETU_ID, reg);
}
Ejemplo n.º 5
0
static irqreturn_t sii9244_irq_thread(int irq, void *data)
{
	struct sii9244_data *sii9244 = data;
	int ret;
	u8 intr1, intr4, value;
	u8 intr1_en, intr4_en;
	bool release_otg = false;

	mutex_lock(&sii9244->lock);
	mhl_tx_read_reg(sii9244, MHL_TX_INTR1_REG, &intr1);
	mhl_tx_read_reg(sii9244, MHL_TX_INTR4_REG, &intr4);

	mhl_tx_read_reg(sii9244, MHL_TX_INTR1_ENABLE_REG, &intr1_en);
	mhl_tx_read_reg(sii9244, MHL_TX_INTR4_ENABLE_REG, &intr4_en);
	pr_debug("sii9244: irq %02x/%02x %02x/%02x\n", intr1, intr1_en,
		 intr4, intr4_en);

	if (intr4 & RGND_READY_INT) {
		ret = mhl_tx_read_reg(sii9244, MHL_TX_STAT2_REG, &value);
		if (ret < 0) {
			dev_err(&sii9244->pdata->mhl_tx_client->dev,
					"STAT2 reg, err %d\n", ret);
			goto err_exit;
		}

		switch (value & RGND_INTP_MASK) {
		case RGND_INTP_OPEN:
			pr_debug("RGND Open\n");
			sii9244->rgnd = RGND_OPEN;
			break;
		case RGND_INTP_1K:
			pr_debug("RGND 1K\n");
			ret = mhl_tx_write_reg(sii9244, MHL_TX_DISC_CTRL1_REG,
					0x25);

			ret = mhl_send_wake_pulses(sii9244);
			sii9244->rgnd = RGND_1K;
			break;
		case RGND_INTP_2K:
			pr_debug("RGND 2K\n");
			ret = mhl_send_wake_pulses(sii9244);
			sii9244->rgnd = RGND_2K;
			break;
		case RGND_INTP_SHORT:
			pr_debug("RGND Short\n");
			sii9244->rgnd = RGND_SHORT;
			break;
		};
	}

	if (intr4 & CBUS_LKOUT_INT) {
		pr_debug("sii9244: CBUS Lockout Interrupt\n");
		sii9244->state = STATE_CBUS_LOCKOUT;
	}

	if (intr4 & MHL_DISC_FAIL_INT)
		sii9244->state = STATE_DISCOVERY_FAILED;

	if (intr4 & MHL_EST_INT) {
		/* discovery override */
		ret = mhl_tx_write_reg(sii9244, MHL_TX_MHLTX_CTL1_REG, 0x10);

		/* increase DDC translation layer timer (byte mode) */
		cbus_write_reg(sii9244, 0x07, 0x32);
		cbus_set_reg(sii9244, 0x44, 1<<1);

		/* Keep the discovery enabled. Need RGND interrupt */
		ret = mhl_tx_set_reg(sii9244, MHL_TX_DISC_CTRL1_REG, (1<<0));

		sii9244->state = STATE_ESTABLISHED;
	}

	if (intr1 & HPD_CHANGE_INT) {
		ret = cbus_read_reg(sii9244, MSC_REQ_ABORT_REASON_REG, &value);

		if (value & SET_HPD_DOWNSTREAM) {
			/* Downstream HPD Highi */

			/* Do we need to send HPD upstream using
			 * Register 0x79(page0)? Is HPD need to be overriden??
			 *      TODO: See if we need code for overriding HPD OUT
			 *      as per Page 0,0x79 Register
			 */

			/* Enable TMDS */
			ret = mhl_tx_set_reg(sii9244, MHL_TX_TMDS_CCTRL,
					     (1<<4));
			pr_debug("sii9244: MHL HPD High, enabled TMDS\n");

			ret = mhl_tx_set_reg(sii9244, MHL_TX_INT_CTRL_REG,
					     (1<<4) | (1<<5));
		} else {
			/*Downstream HPD Low*/

			/* Similar to above comments.
			 * TODO:Do we need to override HPD OUT value
			 * and do we need to disable TMDS here?
			 */

			/* Disable TMDS */
			ret = mhl_tx_clear_reg(sii9244, MHL_TX_TMDS_CCTRL,
					       (1<<4));
			pr_debug("sii9244 MHL HPD low, disabled TMDS\n");
			ret = mhl_tx_clear_reg(sii9244, MHL_TX_INT_CTRL_REG,
					       (1<<4) | (1<<5));
		}
	}

	if (intr1 & RSEN_CHANGE_INT) {
		ret = mhl_tx_read_reg(sii9244, MHL_TX_SYSSTAT_REG, &value);

		sii9244->rsen = value & RSEN_STATUS;

		if (value & RSEN_STATUS) {
			pr_info("sii9244: MHL cable connected.. RESN High\n");
		} else {
			pr_info("sii9244: RSEN lost\n");
			/* Once RSEN loss is confirmed,we need to check
			 * based on cable status and chip power status,whether
			 * it is SINK Loss(HDMI cable not connected, TV Off)
			 * or MHL cable disconnection
			 * TODO: Define the below mhl_disconnection()
			 */
			/* mhl_disconnection(); */
			/* Notify Disconnection to OTG */
			if (sii9244->claimed == true) {
				disable_irq_nosync(sii9244->irq);
				release_otg = true;
			}
			sii9244_power_down(sii9244);
		}
	}

err_exit:
	mhl_tx_write_reg(sii9244, MHL_TX_INTR1_REG, intr1);
	mhl_tx_write_reg(sii9244, MHL_TX_INTR4_REG, intr4);

	mutex_unlock(&sii9244->lock);

	pr_debug("sii9244: wake_up\n");
	wake_up(&sii9244->wq);

	if (release_otg)
		otg_id_notify();

	return IRQ_HANDLED;
}
Ejemplo n.º 6
0
static int sii9244_detection_callback(struct otg_id_notifier_block *nb)
{
	struct sii9244_data *sii9244 = container_of(nb, struct sii9244_data,
						otg_id_nb);
	int ret;
	u8 value;
	int handled = OTG_ID_UNHANDLED;

	pr_debug("sii9244: detection started\n");

	mutex_lock(&sii9244->lock);
	sii9244->rgnd = RGND_UNKNOWN;
	sii9244->state = STATE_DISCONNECTED;
	sii9244->rsen = false;

	/* Set the board configuration so the  sii9244 has access to the
	 * external connector.
	 */
	sii9244->pdata->enable(1);
	sii9244->pdata->power(1);

	ret = sii9244_power_init(sii9244);
	if (ret < 0)
		goto unhandled;

	sii9244_hdmi_init(sii9244);

	sii9244_mhl_tx_ctl_int(sii9244);

	/* Enable HDCP Compliance safety*/
	ret = mhl_tx_write_reg(sii9244, 0x2B, 0x01);
	if (ret < 0)
		goto unhandled;

	/* CBUS discovery cycle time for each drive and float = 150us*/
	ret = mhl_tx_read_reg(sii9244, MHL_TX_DISC_CTRL1_REG, &value);
	if (ret < 0)
		goto unhandled;

	value &= ~(1<<2);
	value |= (1<<3);

	ret = mhl_tx_write_reg(sii9244, MHL_TX_DISC_CTRL1_REG, value);
	if (ret < 0)
		goto unhandled;

	/* Clear bit 6 (reg_skip_rgnd) */
	ret = mhl_tx_write_reg(sii9244, MHL_TX_DISC_CTRL2_REG,
			(1<<7) /* Reserved Bit */ |
			2 << ATT_THRESH_SHIFT |
			DEGLITCH_TIME_128MS);
	if (ret < 0)
		goto unhandled;

	/* Changed from 66 to 65 for 94[1:0] = 01 = 5k reg_cbusmhl_pup_sel */
	/* 1.8V CBUS VTH & GND threshold */
	ret = mhl_tx_write_reg(sii9244, MHL_TX_DISC_CTRL5_REG, 0x75);
	if (ret < 0)
		goto unhandled;

	/* set bit 2 and 3, which is Initiator Timeout */
	ret = cbus_read_reg(sii9244, CBUS_LINK_CONTROL_2_REG, &value);
	if (ret < 0)
		goto unhandled;

	value |= 0x0C;

	ret = cbus_write_reg(sii9244, CBUS_LINK_CONTROL_2_REG, value);
	if (ret < 0)
		goto unhandled;

	ret = mhl_tx_write_reg(sii9244, MHL_TX_MHLTX_CTL6_REG, 0xA0);
	if (ret < 0)
		goto unhandled;

	/* RGND & single discovery attempt (RGND blocking) */
	ret = mhl_tx_write_reg(sii9244, MHL_TX_DISC_CTRL6_REG, BLOCK_RGND_INT |
			DVRFLT_SEL | SINGLE_ATT);
	if (ret < 0)
		goto unhandled;

	/* Use VBUS path of discovery state machine*/
	ret = mhl_tx_write_reg(sii9244, MHL_TX_DISC_CTRL8_REG, 0);
	if (ret < 0)
		goto unhandled;

	ret = mhl_tx_set_reg(sii9244, MHL_TX_DISC_CTRL6_REG, USB_ID_OVR);
	if (ret < 0)
		goto unhandled;

	/* To allow RGND engine to operate correctly.
	 * When moving the chip from D2 to D0 (power up, init regs)
	 * the values should be
	 * 94[1:0] = 01  reg_cbusmhl_pup_sel[1:0] should be set for 5k
	 * 93[7:6] = 10  reg_cbusdisc_pup_sel[1:0] should be
	 * set for 10k (default)
	 * 93[5:4] = 00  reg_cbusidle_pup_sel[1:0] = open (default)
	 */
	ret = mhl_tx_set_reg(sii9244, MHL_TX_DISC_CTRL3_REG, 0x86);
	if (ret < 0)
		goto unhandled;

	/* change from CC to 8C to match 5K*/
	ret = mhl_tx_set_reg(sii9244, MHL_TX_DISC_CTRL4_REG, 0x8C);
	if (ret < 0)
		goto unhandled;

	/* Configure the interrupt as active high */
	ret = mhl_tx_clear_reg(sii9244, MHL_TX_INT_CTRL_REG, (1<<2) | (1<<1));
	if (ret < 0)
		goto unhandled;

	msleep(25);

	ret = mhl_tx_clear_reg(sii9244, MHL_TX_DISC_CTRL6_REG, USB_ID_OVR);
	if (ret < 0)
		goto unhandled;

	ret = mhl_tx_write_reg(sii9244, MHL_TX_DISC_CTRL1_REG, 0x27);
	if (ret < 0)
		goto unhandled;

	/* Reset CBUS */
	ret = mhl_tx_set_reg(sii9244, 0x05, 0x03);
	if (ret < 0)
		goto unhandled;

	usleep_range(2000, 3000);

	ret = mhl_tx_clear_reg(sii9244, 0x05, 0x03);
	if (ret < 0)
		goto unhandled;

	/* Adjust interrupt mask everytime reset is performed.*/
	ret = cbus_write_reg(sii9244, 0x09, 0);
	if (ret < 0)
		goto unhandled;

	ret = cbus_write_reg(sii9244, 0x1F, 0);
	if (ret < 0)
		goto unhandled;

	/* Enable Auto soft reset on SCDT = 0*/
	ret = mhl_tx_write_reg(sii9244, 0x05, 0x04);

	if (ret < 0)
		goto unhandled;

	/* HDMI Transcode mode enable*/
	ret = mhl_tx_write_reg(sii9244, 0x0D, 0x1C);
	if (ret < 0)
		goto unhandled;

	ret = mhl_tx_write_reg(sii9244, MHL_TX_INTR4_ENABLE_REG,
			RGND_READY_MASK | CBUS_LKOUT_MASK |
			MHL_DISC_FAIL_MASK | MHL_EST_MASK);
	if (ret < 0)
		goto unhandled;

	ret = mhl_tx_write_reg(sii9244, MHL_TX_INTR1_ENABLE_REG,
			       (1<<5) | (1<<6));
	if (ret < 0)
		goto unhandled;

	pr_debug("sii9244: waiting for RGND measurement\n");
	enable_irq(sii9244->irq);

	/* SiI9244 Programmer's Reference Section 2.4.3
	 * State : RGND Ready
	 */
	mutex_unlock(&sii9244->lock);
	ret = wait_event_timeout(sii9244->wq,
				 ((sii9244->rgnd != RGND_UNKNOWN) ||
				  mhl_state_is_error(sii9244->state)),
				 msecs_to_jiffies(2000));

	mutex_lock(&sii9244->lock);
	if (sii9244->rgnd == RGND_UNKNOWN || mhl_state_is_error(sii9244->state))
		goto unhandled;

	if (sii9244->rgnd != RGND_1K)
		goto unhandled;

	mutex_unlock(&sii9244->lock);

	pr_debug("sii9244: waiting for detection\n");
	ret = wait_event_timeout(sii9244->wq,
				 sii9244->state != STATE_DISCONNECTED,
				 msecs_to_jiffies(500));
	mutex_lock(&sii9244->lock);
	if (sii9244->state == STATE_DISCONNECTED)
		goto unhandled;

	if (sii9244->state == STATE_DISCOVERY_FAILED) {
		handled = OTG_ID_PROXY_WAIT;
		goto unhandled;
	}

	if (mhl_state_is_error(sii9244->state))
		goto unhandled;

	mutex_unlock(&sii9244->lock);
	wait_event_timeout(sii9244->wq, sii9244->rsen, msecs_to_jiffies(400));
	mutex_lock(&sii9244->lock);
	if (!sii9244->rsen)
		goto unhandled;

	pr_info("si9234: connection established\n");
	sii9244->claimed = true;
	sii9234_vbus_present(true);
	mutex_unlock(&sii9244->lock);

	return OTG_ID_HANDLED;

unhandled:
	pr_info("sii9244: Detection failed");
	if (sii9244->state == STATE_DISCONNECTED)
		pr_cont(" (timeout)");
	else if (sii9244->state == STATE_DISCOVERY_FAILED)
		pr_cont(" (discovery failed)");
	else if (sii9244->state == STATE_CBUS_LOCKOUT)
		pr_cont(" (cbus_lockout)");
	pr_cont("\n");

	disable_irq_nosync(sii9244->irq);

	sii9244_power_down(sii9244);

	mutex_unlock(&sii9244->lock);
	return handled;
}
Ejemplo n.º 7
0
static int sii9234_30pin_reg_init_for_9290(struct sii9234_data *sii9234)
{
    int ret = 0;
    u8 value;
    pr_info("[: %s]++\n", __func__);
    ret = tpi_write_reg(sii9234, 0x3D, 0x3F);
    if (ret < 0)
        return ret;

    ret = hdmi_rx_write_reg(sii9234, 0x11, 0x01);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x12, 0x15);
    if (ret < 0)
        return ret;
    ret = mhl_tx_write_reg(sii9234, 0x08, 0x35);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x00, 0x00);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x13, 0x60);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x14, 0xF0);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x4B, 0x06);
    if (ret < 0)
        return ret;

    /* Analog PLL Control */
    ret = hdmi_rx_write_reg(sii9234, 0x17, 0x07);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x1A, 0x20);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x22, 0xE0);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x23, 0xC0);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x24, 0xA0);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x25, 0x80);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x26, 0x60);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x27, 0x40);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x28, 0x20);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x29, 0x00);
    if (ret < 0)
        return ret;

    ret = hdmi_rx_write_reg(sii9234, 0x4D, 0x02);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x4C, 0xA0);
    if (ret < 0)
        return ret;

    ret = mhl_tx_write_reg(sii9234, 0x80, 0x34);
    if (ret < 0)
        return ret;

    ret = hdmi_rx_write_reg(sii9234, 0x31, 0x0B);
    if (ret < 0)
        return ret;
    ret = hdmi_rx_write_reg(sii9234, 0x45, 0x06);
    if (ret < 0)
        return ret;
    ret = mhl_tx_write_reg(sii9234, 0xA0, 0xD0);
    if (ret < 0)
        return ret;
    ret = mhl_tx_write_reg(sii9234, 0xA1, 0xFC);
    if (ret < 0)
        return ret;

    ret = mhl_tx_write_reg(sii9234, 0xA3 /*MHL_TX_MHLTX_CTL4_REG*/,
                           sii9234->pdata->swing_level);
    if (ret < 0)
        return ret;
    ret = mhl_tx_write_reg(sii9234, 0xA6, 0x00);
    if (ret < 0)
        return ret;

    ret = mhl_tx_write_reg(sii9234, 0x2B, 0x01);
    if (ret < 0)
        return ret;

    /* CBUS & Discovery */
    ret = mhl_tx_read_reg(sii9234, 0x90/*MHL_TX_DISC_CTRL1_REG*/, &value);
    if (ret < 0)
        return ret;
    value &= ~(1<<2);
    value |= (1<<3);
    ret = mhl_tx_write_reg(sii9234, 0x90 /*MHL_TX_DISC_CTRL1_REG*/, value);
    if (ret < 0)
        return ret;

    ret = mhl_tx_write_reg(sii9234, 0x91, 0xE5);
    if (ret < 0)
        return ret;
    ret = mhl_tx_write_reg(sii9234, 0x94, 0x66);
    if (ret < 0)
        return ret;

    ret = cbus_read_reg(sii9234, 0x31, &value);
    if (ret < 0)
        return ret;
    value |= 0x0C;
    if (ret < 0)
        return ret;
    ret = cbus_write_reg(sii9234, 0x31, value);
    if (ret < 0)
        return ret;

    ret = mhl_tx_write_reg(sii9234, 0xA5, 0x80);
    if (ret < 0)
        return ret;
    ret = mhl_tx_write_reg(sii9234, 0x95, 0x31);
    if (ret < 0)
        return ret;
    ret = mhl_tx_write_reg(sii9234, 0x96, 0x22);
    if (ret < 0)
        return ret;

    ret = mhl_tx_read_reg(sii9234, 0x95/*MHL_TX_DISC_CTRL6_REG*/, &value);
    if (ret < 0)
        return ret;
    value |= (1<<6);
    ret = mhl_tx_write_reg(sii9234,  0x95/*MHL_TX_DISC_CTRL6_REG*/, value);
    if (ret < 0)
        return ret;

    ret = mhl_tx_write_reg(sii9234, 0x92, 0x46);
    if (ret < 0)
        return ret;
    ret = mhl_tx_write_reg(sii9234, 0x93, 0xDC);
    if (ret < 0)
        return ret;
    /*0x79=MHL_TX_INT_CTRL_REG*/
    ret = mhl_tx_clear_reg(sii9234, 0x79, (1<<2) | (1<<1));
    if (ret < 0)
        return ret;

    mdelay(25);
    /*0x95=MHL_TX_DISC_CTRL6_REG*/
    ret = mhl_tx_clear_reg(sii9234,  0x95, (1<<6)/*USB_ID_OVR*/);
    if (ret < 0)
        return ret;

    ret = mhl_tx_write_reg(sii9234, 0x90, 0x27);
    if (ret < 0)
        return ret;

    ret = sii9234_cbus_init_for_9290(sii9234);
    if (ret < 0)
        return ret;

    ret = mhl_tx_write_reg(sii9234, 0x05, 0x4);
    if (ret < 0)
        return ret;
    ret = mhl_tx_write_reg(sii9234, 0x0D, 0x1C);
    pr_info("[MHD: %s]--\n", __func__);
    return ret;
}
Ejemplo n.º 8
0
/**
 * retu_read_reg - Read a value from a register in Retu
 * @reg: the register to read from
 *
 * This function returns the contents of the specified register
 */
int retu_read_reg(unsigned reg)
{
	BUG_ON(!retu_initialized);
	return cbus_read_reg(RETU_ID, reg);
}