/*
 * Generic i2c master transfer entrypoint
 */
static int
keywest_xfer(	struct i2c_adapter *adap,
		struct i2c_msg *msgs, 
		int num)
{
	struct keywest_chan* chan = i2c_get_adapdata(adap);
	struct keywest_iface* iface = chan->iface;
	struct i2c_msg *pmsg;
	int i, completed;
	int rc = 0;

	if (iface->state == state_dead)
		return -ENXIO;

	if (pmac_low_i2c_lock(iface->node))
		return -ENXIO;

	/* Set adapter to standard mode */
	iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK;
	iface->cur_mode |= KW_I2C_MODE_STANDARD;

	completed = 0;
	for (i = 0; rc >= 0 && i < num;) {
		u8 addr;
		
		pmsg = &msgs[i++];
		addr = pmsg->addr;
		if (pmsg->flags & I2C_M_TEN) {
			printk(KERN_ERR "i2c-keywest: 10 bits addr not supported !\n");
			rc = -EINVAL;
			break;
		}
		pr_debug("xfer: chan: %d, doing %s %d bytes to 0x%02x - %d of %d messages\n",
		     chan->chan_no,
		     pmsg->flags & I2C_M_RD ? "read" : "write",
                     pmsg->len, addr, i, num);
    
		/* Setup channel & clear pending irqs */
		write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4));
		write_reg(reg_isr, read_reg(reg_isr));
		write_reg(reg_status, 0);
		
		iface->data = pmsg->buf;
		iface->datalen = pmsg->len;
		iface->state = state_addr;
		iface->result = 0;
		if (pmsg->flags & I2C_M_RD)
			iface->read_write = I2C_SMBUS_READ;
		else
			iface->read_write = I2C_SMBUS_WRITE;

		/* Set up address and r/w bit */
		if (pmsg->flags & I2C_M_REV_DIR_ADDR)
			addr ^= 1;		
		write_reg(reg_addr,
			(addr << 1) |
			((iface->read_write == I2C_SMBUS_READ) ? 0x01 : 0x00));

#ifndef POLLED_MODE
		/* Arm timeout */
		iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
		add_timer(&iface->timeout_timer);
#endif

		/* Start sending address & enable interrupt*/
		write_reg(reg_ier, KW_I2C_IRQ_MASK);
		write_reg(reg_control, KW_I2C_CTL_XADDR);

#ifdef POLLED_MODE
		pr_debug("using polled mode...\n");
		/* State machine, to turn into an interrupt handler */
		while(iface->state != state_idle) {
			u8 isr = wait_interrupt(iface);
			handle_interrupt(iface, isr);
		}
#else /* POLLED_MODE */
		pr_debug("using interrupt mode...\n");
		wait_for_completion(&iface->complete);	
#endif /* POLLED_MODE */	

		rc = iface->result;
		if (rc == 0)
			completed++;
		pr_debug("transfer done, result: %d\n", rc);
	}

	/* Release sem */
	pmac_low_i2c_unlock(iface->node);

	return completed;
}
Exemple #2
0
void
FXAS21002C::measure()
{
	/* status register and data as read back from the device */

#pragma pack(push, 1)
	struct {
		uint8_t		cmd;
		uint8_t		status;
		int16_t		x;
		int16_t		y;
		int16_t		z;
	} raw_gyro_report;
#pragma pack(pop)

	struct gyro_report gyro_report;

	/* start the performance counter */
	perf_begin(_sample_perf);

	check_registers();

	if (_register_wait != 0) {
		// we are waiting for some good transfers before using
		// the sensor again.
		_register_wait--;
		perf_end(_sample_perf);
		return;
	}

	/* fetch data from the sensor */
	memset(&raw_gyro_report, 0, sizeof(raw_gyro_report));
	raw_gyro_report.cmd = DIR_READ(FXAS21002C_STATUS);
	transfer((uint8_t *)&raw_gyro_report, (uint8_t *)&raw_gyro_report, sizeof(raw_gyro_report));

	if (!(raw_gyro_report.status & DR_STATUS_ZYXDR)) {
		perf_end(_sample_perf);
		perf_count(_duplicates);
		return;
	}

	/*
	 * The TEMP register contains an 8-bit 2's complement temperature value with a range
	 * of –128 °C to +127 °C and a scaling of 1 °C/LSB. The temperature data is only
	 * compensated (factory trim values applied) when the device is operating in the Active
	 * mode and actively measuring the angular rate.
	 */

	if ((_read % _current_rate) == 0) {
		_last_temperature = read_reg(FXAS21002C_TEMP) * 1.0f;
		gyro_report.temperature = _last_temperature;
	}

	/*
	 * 1) Scale raw value to SI units using scaling from datasheet.
	 * 2) Subtract static offset (in SI units)
	 * 3) Scale the statically calibrated values with a linear
	 *    dynamically obtained factor
	 *
	 * Note: the static sensor offset is the number the sensor outputs
	 * 	 at a nominally 'zero' input. Therefore the offset has to
	 * 	 be subtracted.
	 *
	 *	 Example: A gyro outputs a value of 74 at zero angular rate
	 *	 	  the offset is 74 from the origin and subtracting
	 *		  74 from all measurements centers them around zero.
	 */

	gyro_report.timestamp = hrt_absolute_time();

	// report the error count as the number of bad
	// register reads. This allows the higher level
	// code to decide if it should use this sensor based on
	// whether it has had failures
	gyro_report.error_count = perf_event_count(_bad_registers);

	gyro_report.x_raw = swap16(raw_gyro_report.x);
	gyro_report.y_raw = swap16(raw_gyro_report.y);
	gyro_report.z_raw = swap16(raw_gyro_report.z);

	float xraw_f = gyro_report.x_raw;
	float yraw_f = gyro_report.y_raw;
	float zraw_f = gyro_report.z_raw;

	// apply user specified rotation
	rotate_3f(_rotation, xraw_f, yraw_f, zraw_f);

	float x_in_new = ((xraw_f * _gyro_range_scale) - _gyro_scale.x_offset) * _gyro_scale.x_scale;
	float y_in_new = ((yraw_f * _gyro_range_scale) - _gyro_scale.y_offset) * _gyro_scale.y_scale;
	float z_in_new = ((zraw_f * _gyro_range_scale) - _gyro_scale.z_offset) * _gyro_scale.z_scale;

	gyro_report.x = _gyro_filter_x.apply(x_in_new);
	gyro_report.y = _gyro_filter_y.apply(y_in_new);
	gyro_report.z = _gyro_filter_z.apply(z_in_new);

	math::Vector<3> gval(x_in_new, y_in_new, z_in_new);
	math::Vector<3> gval_integrated;

	bool gyro_notify = _gyro_int.put(gyro_report.timestamp, gval, gval_integrated, gyro_report.integral_dt);
	gyro_report.x_integral = gval_integrated(0);
	gyro_report.y_integral = gval_integrated(1);
	gyro_report.z_integral = gval_integrated(2);

	gyro_report.scaling = _gyro_range_scale;
	gyro_report.range_rad_s = _gyro_range_rad_s;

	/* return device ID */
	gyro_report.device_id = _device_id.devid;


	_reports->force(&gyro_report);

	/* notify anyone waiting for data */
	if (gyro_notify) {
		poll_notify(POLLIN);

		if (!(_pub_blocked)) {
			/* publish it */
			orb_publish(ORB_ID(sensor_gyro), _gyro_topic, &gyro_report);
		}
	}

	_read++;

	/* stop the perf counter */
	perf_end(_sample_perf);
}
static int mipi_samsung_disp_on(struct platform_device *pdev)
{
	struct msm_fb_data_type *mfd;
	struct mipi_panel_info *mipi;
#if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_HD_PT) \
	|| defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT) \
	|| defined(CONFIG_FB_MSM_MIPI_MAGNA_OLED_VIDEO_WVGA_PT)
	static int boot_on;
#endif

	mfd = platform_get_drvdata(pdev);
	if (unlikely(!mfd))
		return -ENODEV;
	if (unlikely(mfd->key != MFD_KEY))
		return -EINVAL;

	mipi = &mfd->panel_info.mipi;

#if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_CMD_QHD_PT)
	mipi_samsung_disp_send_cmd(mfd, MTP_READ_ENABLE, false);
#endif

#if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT) \
	|| defined(CONFIG_FB_MSM_MIPI_MAGNA_OLED_VIDEO_WVGA_PT)
	if (boot_on == 0)
		mipi_samsung_disp_send_cmd(mfd, MTP_READ_ENABLE, false);
#endif

#ifdef USE_READ_ID
#if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT) \
	|| defined(CONFIG_FB_MSM_MIPI_MAGNA_OLED_VIDEO_WVGA_PT)
	if (boot_on == 0)
		msd.mpd->manufacture_id = mipi_samsung_manufacture_id(mfd);
#elif defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_CMD_QHD_PT)
	msd.mpd->manufacture_id = mipi_samsung_manufacture_id(mfd);
#elif defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_HD_PT)
	if (!samsung_has_cmc624())
		msd.mpd->manufacture_id = mipi_samsung_manufacture_id(mfd);
	else
		msd.mpd->manufacture_id = LCD_Get_Value();
#endif
#endif

#if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_CMD_QHD_PT)
	if (!msd.dstat.is_elvss_loaded) {
		read_reg(ELVSS_REGISTER, ELVSS_DATA_SIZE,
			msd.mpd->lcd_elvss_data,
				 FALSE, mfd);  /* read ELVSS data */
		msd.dstat.is_elvss_loaded = true;
	}


	if (!msd.dstat.is_smart_dim_loaded) {
		/* Load MTP Data */
		int i;
		read_reg(MTP_REGISTER, MTP_DATA_SIZE,
				(u8 *)&(msd.mpd->smart_s6e39a0x02.MTP),
						FALSE, mfd);
		for (i = 0; i < MTP_DATA_SIZE; i++) {
			pr_info("%s MTP DATA[%d] : %02x\n", __func__, i,
			((char *)&(msd.mpd->smart_s6e39a0x02.MTP))[i]);
		}

		smart_dimming_init(&(msd.mpd->smart_s6e39a0x02));
#ifdef READ_MTP_ONCE
		msd.dstat.is_smart_dim_loaded = true;
#else
		msd.dstat.is_smart_dim_loaded = false;
#endif
		msd.dstat.gamma_mode = GAMMA_SMART;
	}
#endif
#if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_HD_PT)
	if (!msd.dstat.is_elvss_loaded) {
		if (!samsung_has_cmc624())
			msd.mpd->lcd_elvss_data[0] = elvss_value;
		else
			msd.mpd->lcd_elvss_data[0] = LCD_ID3();

		msd.dstat.is_elvss_loaded = true;
	}

	if (!msd.dstat.is_smart_dim_loaded) {
		/*Load MTP Data*/
		char pBuffer[256] = {0,};
		int i;
		struct SMART_DIM *psmart;
		char *mtp_data;
		int mtp_cnt;

		psmart = &(msd.mpd->smart_s6e8aa0x01);
		mtp_data = (char *)&(msd.mpd->smart_s6e8aa0x01.MTP);

		if (samsung_has_cmc624()) {
			memcpy(mtp_data, mtp_read_data, GAMMA_SET_MAX);
			pr_info("%s This board support CMC", __func__);
		} else {
			mtp_cnt = find_mtp(mfd, mtp_data);
			pr_info("%s MTP is determined : %d", __func__, mtp_cnt);
		}


		for (i = 0; i < MTP_DATA_SIZE; i++)
			snprintf(pBuffer + strnlen(pBuffer, 256), 256, " %02x",
				mtp_data[i]);
		pr_info("MTP: %s", pBuffer);

		psmart->plux_table = msd.mpd->lux_table;
		psmart->lux_table_max = msd.mpd->lux_table_max_cnt;

		if (samsung_has_cmc624())
			psmart->ldi_revision = LCD_Get_Value();
		else
			psmart->ldi_revision = bypass_LCD_Id();

		smart_dimming_init(psmart);

		msd.dstat.is_smart_dim_loaded = true;
		msd.dstat.gamma_mode = GAMMA_SMART;
	}

	if (msd.mpd->gamma_initial && boot_on == 0) {
		msd.mpd->smart_s6e8aa0x01.brightness_level = 180;
		generate_gamma(&msd.mpd->smart_s6e8aa0x01,
			&(msd.mpd->gamma_initial[2]), GAMMA_SET_MAX);

		if (recovery_boot_mode == 0)
			boot_on = 1;
	} else {
		get_min_lux_table(&(msd.mpd->gamma_initial[2]),
					GAMMA_SET_MAX);
		reset_gamma_level();
	}
#endif

#if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT)
	if (!msd.dstat.is_smart_dim_loaded) {
		/* Load MTP Data */
		int i, mtp_cnt, err_cnt;
		char *mtp_data = (char *)&(msd.mpd->smart_s6e63m0.MTP);

		for (err_cnt = 0; err_cnt < 10; err_cnt++) {
			mtp_cnt = find_mtp(mfd, mtp_data);

			if (mtp_cnt != 0)
				break;
		}

		pr_info("%s MTP is determined:%d err_cnt:%d",
					__func__, mtp_cnt, err_cnt);

		for (i = 0; i < MTP_DATA_SIZE_S6E63M0; i++) {
			pr_info("%s MTP DATA[%d] : %02x\n", __func__, i,
				mtp_data[i]);
		}

		smart_dimming_init(&(msd.mpd->smart_s6e63m0));

		msd.dstat.is_smart_dim_loaded = true;
		msd.dstat.gamma_mode = GAMMA_SMART;
	}

	if (msd.mpd->gamma_initial && boot_on == 0) {
		msd.mpd->smart_s6e63m0.brightness_level = 140;
		generate_gamma(&msd.mpd->smart_s6e63m0,
			&(msd.mpd->gamma_initial[2]), GAMMA_SET_MAX);

		if (recovery_boot_mode == 0)
			boot_on = 1;

	} else {
		msd.mpd->smart_s6e63m0.brightness_level = 30;
		generate_gamma(&msd.mpd->smart_s6e63m0,
			&(msd.mpd->gamma_initial[2]), GAMMA_SET_MAX);
		reset_gamma_level();
	}
#endif

#if defined(CONFIG_FB_MSM_MIPI_MAGNA_OLED_VIDEO_WVGA_PT)
	if (!msd.dstat.is_smart_dim_loaded) {
		/* Load MTP Data */
		int i, mtp_cnt, err_cnt;
		char *mtp_data = (char *)&(msd.mpd->smart_ea8868.MTP);

		if (bypass_lcd_id == 0x4a) {
			for (err_cnt = 0; err_cnt < 10; err_cnt++) {
				mtp_cnt = find_mtp(mfd, mtp_data);

				if (mtp_cnt != 0)
					break;
			}

			pr_info("%s MTP is determined:%d err_cnt:%d",
						__func__, mtp_cnt, err_cnt);

			for (i = 0; i < MTP_DATA_SIZE_EA8868; i++) {
				pr_info("%s MTP DATA[%d] : %02x\n",
						__func__, i, mtp_data[i]);
			}
		} else {
			pr_info("%s MTP is not used LDI_ID: 0x%x",
						__func__, bypass_lcd_id);
			memset(mtp_data, 0x0, MTP_DATA_SIZE_EA8868);
		}

		smart_dimming_init(&(msd.mpd->smart_ea8868));

		msd.dstat.is_smart_dim_loaded = true;
		msd.dstat.gamma_mode = GAMMA_SMART;
	}

	if (msd.mpd->gamma_initial && boot_on == 0) {
		msd.mpd->smart_ea8868.brightness_level = 180;
		generate_gamma(&msd.mpd->smart_ea8868,
			&(msd.mpd->gamma_initial[1]), GAMMA_SET_MAX);

		if (recovery_boot_mode == 0)
			boot_on = 1;
	} else {
		msd.mpd->smart_ea8868.brightness_level = get_gamma_lux();
		generate_gamma(&msd.mpd->smart_ea8868,
			&(msd.mpd->gamma_initial[1]), GAMMA_SET_MAX);
		reset_gamma_level();
	}
#endif

	if (unlikely(first_on)) {
		first_on = false;
		return 0;
	}

	mipi_samsung_disp_send_cmd(mfd, PANEL_READY_TO_ON, false);
	if (mipi->mode == DSI_VIDEO_MODE)
		mipi_samsung_disp_send_cmd(mfd, PANEL_ON, false);

#if !defined(CONFIG_HAS_EARLYSUSPEND)
	mipi_samsung_disp_send_cmd(mfd, PANEL_LATE_ON, false);
#endif
#if defined(CONFIG_MIPI_SAMSUNG_ESD_REFRESH)
#if defined(CONFIG_MACH_JAGUAR)
	if  (system_rev >= 16)
		set_esd_enable();
	if (msd.esd_refresh == true)
		mipi_samsung_disp_send_cmd(mfd, PANEL_LATE_ON, false);
#else
	set_esd_enable();
#endif
#endif

#ifdef READ_REGISTER_ESD
	queue_delayed_work(msd.mpd->esd_workqueue,
				&(msd.mpd->esd_work), ESD_INTERVAL * HZ);
	wake_lock(&(msd.mpd->esd_wake_lock));
#endif

	return 0;
}
Exemple #4
0
int HMC5883::set_range(unsigned range)
{
	if (range < 1) {
		_range_bits = 0x00;
		_range_scale = 1.0f / 1370.0f;
		_range_ga = 0.88f;

	} else if (range <= 1) {
		_range_bits = 0x01;
		_range_scale = 1.0f / 1090.0f;
		_range_ga = 1.3f;

	} else if (range <= 2) {
		_range_bits = 0x02;
		_range_scale = 1.0f / 820.0f;
		_range_ga = 1.9f;

	} else if (range <= 3) {
		_range_bits = 0x03;
		_range_scale = 1.0f / 660.0f;
		_range_ga = 2.5f;

	} else if (range <= 4) {
		_range_bits = 0x04;
		_range_scale = 1.0f / 440.0f;
		_range_ga = 4.0f;

	} else if (range <= 4.7f) {
		_range_bits = 0x05;
		_range_scale = 1.0f / 390.0f;
		_range_ga = 4.7f;

	} else if (range <= 5.6f) {
		_range_bits = 0x06;
		_range_scale = 1.0f / 330.0f;
		_range_ga = 5.6f;

	} else {
		_range_bits = 0x07;
		_range_scale = 1.0f / 230.0f;
		_range_ga = 8.1f;
	}

	int ret;

	/*
	 * Send the command to set the range
	 */
	ret = write_reg(ADDR_CONF_B, (_range_bits << 5));

	if (OK != ret)
		perf_count(_comms_errors);

	uint8_t range_bits_in;
	ret = read_reg(ADDR_CONF_B, range_bits_in);

	if (OK != ret)
		perf_count(_comms_errors);

	return !(range_bits_in == (_range_bits << 5));
}
Exemple #5
0
static inline void update_reg(unsigned int reg, u32 or_val)
{
	u32 newval = read_reg(reg) | or_val;
	write_reg(reg, newval);
}
Exemple #6
0
static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
	ide_hwif_t *hwif = drive->hwif;
	ide_drive_t *pair = ide_get_paired_drive(drive);
	unsigned long flags;
	u8 tim, misc, addr_pio = pio, clk;

	/* DRDY is default 2 (by OPTi Databook) */
	static const u8 addr_timings[2][5] = {
		{ 0x20, 0x10, 0x00, 0x00, 0x00 },	/* 33 MHz */
		{ 0x10, 0x10, 0x00, 0x00, 0x00 },	/* 25 MHz */
	};
	static const u8 data_rec_timings[2][5] = {
		{ 0x5b, 0x45, 0x32, 0x21, 0x20 },	/* 33 MHz */
		{ 0x48, 0x34, 0x21, 0x10, 0x10 }	/* 25 MHz */
	};

	drive->drive_data = XFER_PIO_0 + pio;

	if (pair->present) {
		if (pair->drive_data && pair->drive_data < drive->drive_data)
			addr_pio = pair->drive_data - XFER_PIO_0;
	}

	spin_lock_irqsave(&opti621_lock, flags);

	reg_base = hwif->io_ports.data_addr;

	/* allow Register-B */
	outb(0xc0, reg_base + CNTRL_REG);
	/* hmm, setupvic.exe does this ;-) */
	outb(0xff, reg_base + 5);
	/* if reads 0xff, adapter not exist? */
	(void)inb(reg_base + CNTRL_REG);
	/* if reads 0xc0, no interface exist? */
	read_reg(CNTRL_REG);

	/* check CLK speed */
	clk = read_reg(STRAP_REG) & 1;

	printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33);

	tim  = data_rec_timings[clk][pio];
	misc = addr_timings[clk][addr_pio];

	/* select Index-0/1 for Register-A/B */
	write_reg(drive->select.b.unit, MISC_REG);
	/* set read cycle timings */
	write_reg(tim, READ_REG);
	/* set write cycle timings */
	write_reg(tim, WRITE_REG);

	/* use Register-A for drive 0 */
	/* use Register-B for drive 1 */
	write_reg(0x85, CNTRL_REG);

	/* set address setup, DRDY timings,   */
	/*  and read prefetch for both drives */
	write_reg(misc, MISC_REG);

	spin_unlock_irqrestore(&opti621_lock, flags);
}
Exemple #7
0
int
AK8975::collect()
{
#pragma pack(push, 1)
	struct { /* status register and data as read back from the device */
		uint8_t		x[2];
		uint8_t		y[2];
		uint8_t		z[2];
	}	ak8975_report;
#pragma pack(pop)
	struct {
		int16_t		x, y, z;
	} report;
	int	ret = -EIO;
	uint8_t	cmd;


	perf_begin(_sample_perf);
	struct mag_report new_report;

	/* this should be fairly close to the end of the measurement, so the best approximation of the time */
	new_report.timestamp = hrt_absolute_time();
        new_report.error_count = perf_event_count(_comms_errors);

	/*
	 * @note  We could read the status register here, which could tell us that
	 *        we were too early and that the output registers are still being
	 *        written.  In the common case that would just slow us down, and
	 *        we're better off just never being early.
	 */
	/* check data ready bit */	
	if (read_reg(ADDR_DRDY, cmd)) {
		perf_count(_comms_errors);
		debug("data ready read error");
		goto out;	
	}
	if (!(cmd & STATUS_REG_DATA_READY)) {
		/* data not ready */
		perf_count(_comms_errors);
		debug("data not ready [%02X]", cmd);
		goto out;
	}

	/* get measurements from the device */
	cmd = ADDR_DATA_OUT_X_LSB;
	ret = transfer(&cmd, 1, (uint8_t *)&ak8975_report, sizeof(ak8975_report));

	if (ret != OK) {
		perf_count(_comms_errors);
		debug("data/status read error");
		goto out;
	}
	/* check for overflow and not ready error */
	if (read_reg(ADDR_STATUS, cmd)) {
		perf_count(_comms_errors);
		debug("data status read error");
		goto out;	
	}
	if (cmd & (STATUS_REG_DATA_ERROR | STATUS_REG_HOFL)) {
		/* data value error  */
		perf_count(_comms_errors);
		debug("data value error");
		goto out;
	}

	/* swap the data we just received */
	report.x = (((int16_t)ak8975_report.x[1]) << 8) + ak8975_report.x[0];
	report.y = (((int16_t)ak8975_report.y[1]) << 8) + ak8975_report.y[0];
	report.z = (((int16_t)ak8975_report.z[1]) << 8) + ak8975_report.z[0];

	/*
	 * If any of the values are -4096, there was an internal math error in the sensor.
	 * Generalise this to a simple range check that will also catch some bit errors.
	 */
	if ((abs(report.x) > 4096) ||
	    (abs(report.y) > 4096) ||
	    (abs(report.z) > 4096)) {
		perf_count(_comms_errors);
		goto out;
	}

	/*
	 * RAW outputs
	 *
	 * to align the sensor axes with the board, x and y need to be flipped
	 * and y needs to be negated
	 */
	new_report.x_raw = report.x;
	new_report.y_raw = report.y;
	/* z remains z */
	new_report.z_raw = report.z;

	/* scale values for output */

	/*
	 * 1) Scale raw value to SI units using scaling from datasheet.
	 * 2) Subtract static offset (in SI units)
	 * 3) Scale the statically calibrated values with a linear
	 *    dynamically obtained factor
	 *
	 * Note: the static sensor offset is the number the sensor outputs
	 * 	 at a nominally 'zero' input. Therefore the offset has to
	 * 	 be subtracted.
	 *
	 *	 Example: A gyro outputs a value of 74 at zero angular rate
	 *	 	  the offset is 74 from the origin and subtracting
	 *		  74 from all measurements centers them around zero.
	 */

	/* the standard external mag by 3DR has x pointing to the right, y pointing backwards, and z down,
	 * therefore switch x and y and invert y */
	//new_report.x = ((-report.y * _range_scale) - _scale.x_offset) * _scale.x_scale;
	new_report.x = ((report.x * _scale.x_scale) - _scale.x_offset) * _range_scale;
	/* flip axes and negate value for y */
	//new_report.y = ((report.x * _range_scale) - _scale.y_offset) * _scale.y_scale;
	new_report.y = ((report.y * _scale.y_scale) - _scale.y_offset) * _range_scale;
	/* z remains z */
	//new_report.z = ((report.z * _range_scale) - _scale.z_offset) * _scale.z_scale;
	new_report.z = ((report.z * _scale.z_scale) - _scale.z_offset) * _range_scale;

	/* publish it */
	orb_publish(ORB_ID(sensor_mag), _mag_topic, &new_report);

	/* post a report to the ring */
	if (_reports->force(&new_report)) {
		perf_count(_buffer_overflows);
	}

	/* notify anyone waiting for data */
	poll_notify(POLLIN);

	ret = OK;

out:
	perf_end(_sample_perf);
	return ret;
}
LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {

    unsigned short DeviceCode;

    // No private area for this controller
    g->priv = 0;

    // Initialise the board interface
    init_board(g);

    /* Hardware reset */
    setpin_reset(g, TRUE);
    gfxSleepMilliseconds(1);
    setpin_reset(g, FALSE);
    gfxSleepMilliseconds(10);
    setpin_reset(g, TRUE);
    gfxSleepMilliseconds(50);

    acquire_bus(g);
    setreadmode(g);
    DeviceCode = read_reg(g, 0x00);
    setwritemode(g);

    if( DeviceCode == 0x9320 || DeviceCode == 0x9300 )
    {
        write_reg(g, 0x00, 0x0000);
        write_reg(g, 0x01, 0x0100); /* Driver Output Contral */
        write_reg(g, 0x02, 0x0700); /* LCD Driver Waveform Contral */
        write_reg(g, 0x03, 0x1038); /* Set the scan mode */
        write_reg(g, 0x04, 0x0000); /* Scalling Contral */
        write_reg(g, 0x08, 0x0202); /* Display Contral 2 */
        write_reg(g, 0x09, 0x0000); /* Display Contral 3 */
        write_reg(g, 0x0a, 0x0000); /* Frame Cycle Contal */
        write_reg(g, 0x0c, (1<<0)); /* Extern Display Interface Contral 1 */
        write_reg(g, 0x0d, 0x0000); /* Frame Maker Position */
        write_reg(g, 0x0f, 0x0000); /* Extern Display Interface Contral 2 */
        gfxSleepMilliseconds(50);
        write_reg(g, 0x07, 0x0101); /* Display Contral */
        gfxSleepMilliseconds(50);
        write_reg(g, 0x10, (1<<12)|(0<<8)|(1<<7)|(1<<6)|(0<<4)); /* Power Control 1 */
        write_reg(g, 0x11, 0x0007);                              /* Power Control 2 */
        write_reg(g, 0x12, (1<<8)|(1<<4)|(0<<0));                /* Power Control 3 */
        write_reg(g, 0x13, 0x0b00);                              /* Power Control 4 */
        write_reg(g, 0x29, 0x0000);                              /* Power Control 7 */
        write_reg(g, 0x2b, (1<<14)|(1<<4));
        write_reg(g, 0x50, 0);       /* Set X Start */
        write_reg(g, 0x51, 239);     /* Set X End */
        write_reg(g, 0x52, 0);       /* Set Y Start */
        write_reg(g, 0x53, 319);     /* Set Y End */
        gfxSleepMilliseconds(50);

        write_reg(g, 0x60, 0x2700); /* Driver Output Control */
        write_reg(g, 0x61, 0x0001); /* Driver Output Control */
        write_reg(g, 0x6a, 0x0000); /* Vertical Srcoll Control */

        write_reg(g, 0x80, 0x0000); /* Display Position? Partial Display 1 */
        write_reg(g, 0x81, 0x0000); /* RAM Address Start? Partial Display 1 */
        write_reg(g, 0x82, 0x0000); /* RAM Address End-Partial Display 1 */
        write_reg(g, 0x83, 0x0000); /* Displsy Position? Partial Display 2 */
        write_reg(g, 0x84, 0x0000); /* RAM Address Start? Partial Display 2 */
        write_reg(g, 0x85, 0x0000); /* RAM Address End? Partial Display 2 */

        write_reg(g, 0x90, (0<<7)|(16<<0)); /* Frame Cycle Contral */
        write_reg(g, 0x92, 0x0000);         /* Panel Interface Contral 2 */
        write_reg(g, 0x93, 0x0001);         /* Panel Interface Contral 3 */
        write_reg(g, 0x95, 0x0110);         /* Frame Cycle Contral */
        write_reg(g, 0x97, (0<<8));
        write_reg(g, 0x98, 0x0000);         /* Frame Cycle Contral */
        write_reg(g, 0x07, 0x0133);
    }
    else if( DeviceCode == 0x9325 || DeviceCode == 0x9328)
    {

        write_reg(g, 0x00e7, 0x0010);
        write_reg(g, 0x0000, 0x0001);    /* start internal osc */
        write_reg(g, 0x0001, 0x0100);
        write_reg(g, 0x0002, 0x0700);    /* power on sequence */
        write_reg(g, 0x0003, (1<<12)|(1<<5)|(1<<4)|(0<<3) );     /* importance */
        write_reg(g, 0x0004, 0x0000);
        write_reg(g, 0x0008, 0x0207);
        write_reg(g, 0x0009, 0x0000);
        write_reg(g, 0x000a, 0x0000);    /* display setting */
        write_reg(g, 0x000c, 0x0001);    /* display setting */
        write_reg(g, 0x000d, 0x0000);
        write_reg(g, 0x000f, 0x0000);
        /* Power On sequence */
        write_reg(g, 0x0010, 0x0000);
        write_reg(g, 0x0011, 0x0007);
        write_reg(g, 0x0012, 0x0000);
        write_reg(g, 0x0013, 0x0000);
        gfxSleepMilliseconds(50);  /* delay 50 ms */
        write_reg(g, 0x0010, 0x1590);
        write_reg(g, 0x0011, 0x0227);
        gfxSleepMilliseconds(50);  /* delay 50 ms */
        write_reg(g, 0x0012, 0x009c);
        gfxSleepMilliseconds(50);  /* delay 50 ms */
        write_reg(g, 0x0013, 0x1900);
        write_reg(g, 0x0029, 0x0023);
        write_reg(g, 0x002b, 0x000e);
        gfxSleepMilliseconds(50);  /* delay 50 ms */
        write_reg(g, 0x0020, 0x0000);
        write_reg(g, 0x0021, 0x0000);
        gfxSleepMilliseconds(50);  /* delay 50 ms */
        write_reg(g, 0x0030, 0x0007);
        write_reg(g, 0x0031, 0x0707);
        write_reg(g, 0x0032, 0x0006);
        write_reg(g, 0x0035, 0x0704);
        write_reg(g, 0x0036, 0x1f04);
        write_reg(g, 0x0037, 0x0004);
        write_reg(g, 0x0038, 0x0000);
        write_reg(g, 0x0039, 0x0706);
        write_reg(g, 0x003c, 0x0701);
        write_reg(g, 0x003d, 0x000f);
        gfxSleepMilliseconds(50);  /* delay 50 ms */
        write_reg(g, 0x0050, 0x0000);
        write_reg(g, 0x0051, 0x00ef);
        write_reg(g, 0x0052, 0x0000);
        write_reg(g, 0x0053, 0x013f);
        write_reg(g, 0x0060, 0xa700);
        write_reg(g, 0x0061, 0x0001);
        write_reg(g, 0x006a, 0x0000);
        write_reg(g, 0x0080, 0x0000);
        write_reg(g, 0x0081, 0x0000);
        write_reg(g, 0x0082, 0x0000);
        write_reg(g, 0x0083, 0x0000);
        write_reg(g, 0x0084, 0x0000);
        write_reg(g, 0x0085, 0x0000);

        write_reg(g, 0x0090, 0x0010);
        write_reg(g, 0x0092, 0x0000);
        write_reg(g, 0x0093, 0x0003);
        write_reg(g, 0x0095, 0x0110);
        write_reg(g, 0x0097, 0x0000);
        write_reg(g, 0x0098, 0x0000);
        /* display on sequence */
        write_reg(g, 0x0007, 0x0133);

        write_reg(g, 0x0020, 0x0000);
        write_reg(g, 0x0021, 0x0000);
    }

    gfxSleepMilliseconds(100);   /* delay 50 ms */


    // Finish Init
    post_init_board(g);

    // Release the bus
    release_bus(g);

    // Turn on the backlight
    set_backlight(g, GDISP_INITIAL_BACKLIGHT);

    /* Initialise the GDISP structure */
    g->g.Width = GDISP_SCREEN_WIDTH;
    g->g.Height = GDISP_SCREEN_HEIGHT;
    g->g.Orientation = GDISP_ROTATE_0;
    g->g.Powermode = powerOn;
    g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
    g->g.Contrast = GDISP_INITIAL_CONTRAST;

    return TRUE;
}
Exemple #9
0
void
LSM303D::measure()
{
	// if the accel doesn't have any data ready then re-schedule
	// for 100 microseconds later. This ensures we don't double
	// read a value and then miss the next value
	if (stm32_gpioread(GPIO_EXTI_ACCEL_DRDY) == 0) {
		perf_count(_accel_reschedules);
		hrt_call_delay(&_accel_call, 100);
		return;
	}
	if (read_reg(ADDR_CTRL_REG1) != _reg1_expected) {
		perf_count(_reg1_resets);
		reset();
		return;
	}

	/* status register and data as read back from the device */

#pragma pack(push, 1)
	struct {
		uint8_t		cmd;
		uint8_t		status;
		int16_t		x;
		int16_t		y;
		int16_t		z;
	} raw_accel_report;
#pragma pack(pop)

	accel_report accel_report;

	/* start the performance counter */
	perf_begin(_accel_sample_perf);

	/* fetch data from the sensor */
	memset(&raw_accel_report, 0, sizeof(raw_accel_report));
	raw_accel_report.cmd = ADDR_STATUS_A | DIR_READ | ADDR_INCREMENT;
	transfer((uint8_t *)&raw_accel_report, (uint8_t *)&raw_accel_report, sizeof(raw_accel_report));

	/*
	 * 1) Scale raw value to SI units using scaling from datasheet.
	 * 2) Subtract static offset (in SI units)
	 * 3) Scale the statically calibrated values with a linear
	 *    dynamically obtained factor
	 *
	 * Note: the static sensor offset is the number the sensor outputs
	 * 	 at a nominally 'zero' input. Therefore the offset has to
	 * 	 be subtracted.
	 *
	 *	 Example: A gyro outputs a value of 74 at zero angular rate
	 *	 	  the offset is 74 from the origin and subtracting
	 *		  74 from all measurements centers them around zero.
	 */


	accel_report.timestamp = hrt_absolute_time();
        accel_report.error_count = 0; // not reported

	accel_report.x_raw = raw_accel_report.x;
	accel_report.y_raw = raw_accel_report.y;
	accel_report.z_raw = raw_accel_report.z;

	float x_in_new = ((accel_report.x_raw * _accel_range_scale) - _accel_scale.x_offset) * _accel_scale.x_scale;
	float y_in_new = ((accel_report.y_raw * _accel_range_scale) - _accel_scale.y_offset) * _accel_scale.y_scale;
	float z_in_new = ((accel_report.z_raw * _accel_range_scale) - _accel_scale.z_offset) * _accel_scale.z_scale;

	accel_report.x = _accel_filter_x.apply(x_in_new);
	accel_report.y = _accel_filter_y.apply(y_in_new);
	accel_report.z = _accel_filter_z.apply(z_in_new);

	accel_report.scaling = _accel_range_scale;
	accel_report.range_m_s2 = _accel_range_m_s2;

	_accel_reports->force(&accel_report);

	/* notify anyone waiting for data */
	poll_notify(POLLIN);

	if (_accel_topic != -1) {
		/* publish for subscribers */
		orb_publish(ORB_ID(sensor_accel), _accel_topic, &accel_report);
	}

	_accel_read++;

	/* stop the perf counter */
	perf_end(_accel_sample_perf);
}
Exemple #10
0
/* Read the serial data line */
static int ivtv_getsda(struct ivtv *itv)
{
	return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1;
}
Exemple #11
0
static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
{
	struct ivtv *itv = s->itv;
	struct ivtv_open_id *item;

	IVTV_DEBUG_FILE("open %s\n", s->name);

	if (s->type == IVTV_DEC_STREAM_TYPE_MPG &&
		test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags))
		return -EBUSY;

	if (s->type == IVTV_DEC_STREAM_TYPE_YUV &&
		test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags))
		return -EBUSY;

	if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
		if (read_reg(0x82c) == 0) {
			IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n");
			/* return -ENODEV; */
		}
		ivtv_udma_alloc(itv);
	}

	/* Allocate memory */
	item = kmalloc(sizeof(struct ivtv_open_id), GFP_KERNEL);
	if (NULL == item) {
		IVTV_DEBUG_WARN("nomem on v4l2 open\n");
		return -ENOMEM;
	}
	item->itv = itv;
	item->type = s->type;
	v4l2_prio_open(&itv->prio, &item->prio);

	item->open_id = itv->open_id++;
	filp->private_data = item;

	if (item->type == IVTV_ENC_STREAM_TYPE_RAD) {
		/* Try to claim this stream */
		if (ivtv_claim_stream(item, item->type)) {
			/* No, it's already in use */
			kfree(item);
			return -EBUSY;
		}

		if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
			if (atomic_read(&itv->capturing) > 0) {
				/* switching to radio while capture is
				   in progress is not polite */
				ivtv_release_stream(s);
				kfree(item);
				return -EBUSY;
			}
		}
		/* Mark that the radio is being used. */
		set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
		/* We have the radio */
		ivtv_mute(itv);
		/* Switch tuner to radio */
		ivtv_call_all(itv, tuner, s_radio);
		/* Select the correct audio input (i.e. radio tuner) */
		ivtv_audio_set_io(itv);
		if (itv->hw_flags & IVTV_HW_SAA711X) {
			ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq,
				SAA7115_FREQ_32_11_MHZ, SAA7115_FREQ_FL_APLL);
		}
		/* Done! Unmute and continue. */
		ivtv_unmute(itv);
	}

	/* YUV or MPG Decoding Mode? */
	if (s->type == IVTV_DEC_STREAM_TYPE_MPG) {
		clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
	} else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
		set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
		/* For yuv, we need to know the dma size before we start */
		itv->dma_data_req_size =
				1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
		itv->yuv_info.stream_size = 0;
	}
	return 0;
}
Exemple #12
0
int NRF24L01::read_test(void)
{
return read_reg(SETUP_AW);
}
Exemple #13
0
int NRF24L01::status(void)
{
return read_reg(STATUS);
}
Exemple #14
0
void
BMI055_accel::measure()
{
	uint8_t index = 0, accel_data[7];
	uint16_t lsb, msb, msblsb;
	uint8_t status_x, status_y, status_z;

	if (hrt_absolute_time() < _reset_wait) {
		// we're waiting for a reset to complete
		return;
	}

	struct Report {
		int16_t     accel_x;
		int16_t     accel_y;
		int16_t     accel_z;
		int16_t     temp;
	} report;

	/* start measuring */
	perf_begin(_sample_perf);

	/*
	 * Fetch the full set of measurements from the BMI055 in one pass.
	 */
	accel_data[index] = BMI055_ACC_X_L | DIR_READ;

	if (OK != transfer(accel_data, accel_data, sizeof(accel_data))) {
		return;
	}

	check_registers();

	/* Extracting accel data from the read data */
	index = 1;
	lsb = (uint16_t)accel_data[index++];
	status_x = (lsb & BMI055_NEW_DATA_MASK);
	msb = (uint16_t)accel_data[index++];
	msblsb = (msb << 8) | lsb;
	report.accel_x = ((int16_t)msblsb >> 4); /* Data in X axis */

	lsb = (uint16_t)accel_data[index++];
	status_y = (lsb & BMI055_NEW_DATA_MASK);
	msb = (uint16_t)accel_data[index++];
	msblsb = (msb << 8) | lsb;
	report.accel_y = ((int16_t)msblsb >> 4); /* Data in Y axis */

	lsb = (uint16_t)accel_data[index++];
	status_z = (lsb & BMI055_NEW_DATA_MASK);
	msb = (uint16_t)accel_data[index++];
	msblsb = (msb << 8) | lsb;
	report.accel_z = ((int16_t)msblsb >> 4); /* Data in Z axis */

	// Checking the status of new data
	if ((!status_x) || (!status_y) || (!status_z)) {
		perf_end(_sample_perf);
		perf_count(_duplicates);
		_got_duplicate = true;
		return;
	}


	_got_duplicate = false;

	uint8_t temp = read_reg(BMI055_ACC_TEMP);
	report.temp = temp;

	if (report.accel_x == 0 &&
	    report.accel_y == 0 &&
	    report.accel_z == 0 &&
	    report.temp == 0) {
		// all zero data - probably a SPI bus error
		perf_count(_bad_transfers);
		perf_end(_sample_perf);
		// note that we don't call reset() here as a reset()
		// costs 20ms with interrupts disabled. That means if
		// the bmi055 accel does go bad it would cause a FMU failure,
		// regardless of whether another sensor is available,
		return;
	}


	perf_count(_good_transfers);

	if (_register_wait != 0) {
		// we are waiting for some good transfers before using
		// the sensor again. We still increment
		// _good_transfers, but don't return any data yet
		_register_wait--;
		return;
	}

	/*
	 * Report buffers.
	 */
	accel_report        arb;


	arb.timestamp = hrt_absolute_time();


	// report the error count as the sum of the number of bad
	// transfers and bad register reads. This allows the higher
	// level code to decide if it should use this sensor based on
	// whether it has had failures
	arb.error_count = perf_event_count(_bad_transfers) + perf_event_count(_bad_registers);

	/*
	 * 1) Scale raw value to SI units using scaling from datasheet.
	 * 2) Subtract static offset (in SI units)
	 * 3) Scale the statically calibrated values with a linear
	 *    dynamically obtained factor
	 *
	 * Note: the static sensor offset is the number the sensor outputs
	 *   at a nominally 'zero' input. Therefore the offset has to
	 *   be subtracted.
	 *
	 */

	arb.x_raw = report.accel_x;
	arb.y_raw = report.accel_y;
	arb.z_raw = report.accel_z;

	float xraw_f = report.accel_x;
	float yraw_f = report.accel_y;
	float zraw_f = report.accel_z;

	// apply user specified rotation
	rotate_3f(_rotation, xraw_f, yraw_f, zraw_f);

	float x_in_new = ((xraw_f * _accel_range_scale) - _accel_scale.x_offset) * _accel_scale.x_scale;
	float y_in_new = ((yraw_f * _accel_range_scale) - _accel_scale.y_offset) * _accel_scale.y_scale;
	float z_in_new = ((zraw_f * _accel_range_scale) - _accel_scale.z_offset) * _accel_scale.z_scale;

	arb.x = _accel_filter_x.apply(x_in_new);
	arb.y = _accel_filter_y.apply(y_in_new);
	arb.z = _accel_filter_z.apply(z_in_new);

	math::Vector<3> aval(x_in_new, y_in_new, z_in_new);
	math::Vector<3> aval_integrated;

	bool accel_notify = _accel_int.put(arb.timestamp, aval, aval_integrated, arb.integral_dt);
	arb.x_integral = aval_integrated(0);
	arb.y_integral = aval_integrated(1);
	arb.z_integral = aval_integrated(2);

	arb.scaling = _accel_range_scale;
	arb.range_m_s2 = _accel_range_m_s2;

	_last_temperature = 23 + report.temp * 1.0f / 512.0f;

	arb.temperature_raw = report.temp;
	arb.temperature = _last_temperature;
	arb.device_id = _device_id.devid;

	_accel_reports->force(&arb);

	/* notify anyone waiting for data */
	if (accel_notify) {
		poll_notify(POLLIN);
	}

	if (accel_notify && !(_pub_blocked)) {
		/* log the time of this report */
		perf_begin(_controller_latency_perf);
		/* publish it */
		orb_publish(ORB_ID(sensor_accel), _accel_topic, &arb);
	}

	/* stop measuring */
	perf_end(_sample_perf);
}
Exemple #15
0
static int ivtv_open(struct file *filp)
{
	struct video_device *vdev = video_devdata(filp);
	struct ivtv_stream *s = video_get_drvdata(vdev);
	struct ivtv *itv = s->itv;
	struct ivtv_open_id *item;
	int res = 0;

	IVTV_DEBUG_FILE("open %s\n", s->name);

	if (ivtv_init_on_first_open(itv)) {
		IVTV_ERR("Failed to initialize on device %s\n",
			 video_device_node_name(vdev));
		return -ENXIO;
	}

#ifdef CONFIG_VIDEO_ADV_DEBUG
	/* Unless ivtv_fw_debug is set, error out if firmware dead. */
	if (ivtv_fw_debug) {
		IVTV_WARN("Opening %s with dead firmware lockout disabled\n",
			  video_device_node_name(vdev));
		IVTV_WARN("Selected firmware errors will be ignored\n");
	} else {
#else
	if (1) {
#endif
		res = ivtv_firmware_check(itv, "ivtv_serialized_open");
		if (res == -EAGAIN)
			res = ivtv_firmware_check(itv, "ivtv_serialized_open");
		if (res < 0)
			return -EIO;
	}

	if (s->type == IVTV_DEC_STREAM_TYPE_MPG &&
		test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags))
		return -EBUSY;

	if (s->type == IVTV_DEC_STREAM_TYPE_YUV &&
		test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags))
		return -EBUSY;

	if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
		if (read_reg(0x82c) == 0) {
			IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n");
			/* return -ENODEV; */
		}
		ivtv_udma_alloc(itv);
	}

	/* Allocate memory */
	item = kzalloc(sizeof(struct ivtv_open_id), GFP_KERNEL);
	if (NULL == item) {
		IVTV_DEBUG_WARN("nomem on v4l2 open\n");
		return -ENOMEM;
	}
	v4l2_fh_init(&item->fh, &s->vdev);
	item->itv = itv;
	item->type = s->type;

	filp->private_data = &item->fh;
	v4l2_fh_add(&item->fh);

	if (item->type == IVTV_ENC_STREAM_TYPE_RAD &&
			v4l2_fh_is_singular_file(filp)) {
		if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
			if (atomic_read(&itv->capturing) > 0) {
				/* switching to radio while capture is
				   in progress is not polite */
				v4l2_fh_del(&item->fh);
				v4l2_fh_exit(&item->fh);
				kfree(item);
				return -EBUSY;
			}
		}
		/* Mark that the radio is being used. */
		set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
		/* We have the radio */
		ivtv_mute(itv);
		/* Switch tuner to radio */
		ivtv_call_all(itv, tuner, s_radio);
		/* Select the correct audio input (i.e. radio tuner) */
		ivtv_audio_set_io(itv);
		if (itv->hw_flags & IVTV_HW_SAA711X) {
			ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq,
				SAA7115_FREQ_32_11_MHZ, SAA7115_FREQ_FL_APLL);
		}
		/* Done! Unmute and continue. */
		ivtv_unmute(itv);
	}

	/* YUV or MPG Decoding Mode? */
	if (s->type == IVTV_DEC_STREAM_TYPE_MPG) {
		clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
	} else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
		set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
		/* For yuv, we need to know the dma size before we start */
		itv->dma_data_req_size =
				1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
		itv->yuv_info.stream_size = 0;
	}
	return 0;
}

int ivtv_v4l2_open(struct file *filp)
{
	struct video_device *vdev = video_devdata(filp);
	int res;

	if (mutex_lock_interruptible(vdev->lock))
		return -ERESTARTSYS;
	res = ivtv_open(filp);
	mutex_unlock(vdev->lock);
	return res;
}

void ivtv_mute(struct ivtv *itv)
{
	if (atomic_read(&itv->capturing))
		ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 1);
	IVTV_DEBUG_INFO("Mute\n");
}

void ivtv_unmute(struct ivtv *itv)
{
	if (atomic_read(&itv->capturing)) {
		ivtv_msleep_timeout(100, 0);
		ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
		ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0);
	}
	IVTV_DEBUG_INFO("Unmute\n");
}
Exemple #16
0
void
LSM303D::mag_measure()
{
	if (read_reg(ADDR_CTRL_REG7) != _reg7_expected) {
		perf_count(_reg7_resets);
		reset();
		return;
	}

	/* status register and data as read back from the device */
#pragma pack(push, 1)
	struct {
		uint8_t		cmd;
		uint8_t		status;
		int16_t		x;
		int16_t		y;
		int16_t		z;
	} raw_mag_report;
#pragma pack(pop)

	mag_report mag_report;

	/* start the performance counter */
	perf_begin(_mag_sample_perf);

	/* fetch data from the sensor */
	memset(&raw_mag_report, 0, sizeof(raw_mag_report));
	raw_mag_report.cmd = ADDR_STATUS_M | DIR_READ | ADDR_INCREMENT;
	transfer((uint8_t *)&raw_mag_report, (uint8_t *)&raw_mag_report, sizeof(raw_mag_report));

	/*
	 * 1) Scale raw value to SI units using scaling from datasheet.
	 * 2) Subtract static offset (in SI units)
	 * 3) Scale the statically calibrated values with a linear
	 *    dynamically obtained factor
	 *
	 * Note: the static sensor offset is the number the sensor outputs
	 * 	 at a nominally 'zero' input. Therefore the offset has to
	 * 	 be subtracted.
	 *
	 *	 Example: A gyro outputs a value of 74 at zero angular rate
	 *	 	  the offset is 74 from the origin and subtracting
	 *		  74 from all measurements centers them around zero.
	 */


	mag_report.timestamp = hrt_absolute_time();

	mag_report.x_raw = raw_mag_report.x;
	mag_report.y_raw = raw_mag_report.y;
	mag_report.z_raw = raw_mag_report.z;
	mag_report.x = ((mag_report.x_raw * _mag_range_scale) - _mag_scale.x_offset) * _mag_scale.x_scale;
	mag_report.y = ((mag_report.y_raw * _mag_range_scale) - _mag_scale.y_offset) * _mag_scale.y_scale;
	mag_report.z = ((mag_report.z_raw * _mag_range_scale) - _mag_scale.z_offset) * _mag_scale.z_scale;
	mag_report.scaling = _mag_range_scale;
	mag_report.range_ga = (float)_mag_range_ga;

	_mag_reports->force(&mag_report);

	/* XXX please check this poll_notify, is it the right one? */
	/* notify anyone waiting for data */
	poll_notify(POLLIN);

	if (_mag->_mag_topic != -1) {
		/* publish for subscribers */
		orb_publish(ORB_ID(sensor_mag), _mag->_mag_topic, &mag_report);
	}

	_mag_read++;

	/* stop the perf counter */
	perf_end(_mag_sample_perf);
}
Exemple #17
0
void
BMA180::measure()
{
	/* BMA180 measurement registers */
// #pragma pack(push, 1)
// 	struct {
// 		uint8_t		cmd;
// 		int16_t	x;
// 		int16_t	y;
// 		int16_t	z;
// 	} raw_report;
// #pragma pack(pop)

	struct accel_report report;

	/* start the performance counter */
	perf_begin(_sample_perf);

	/*
	 * Fetch the full set of measurements from the BMA180 in one pass;
	 * starting from the X LSB.
	 */
	//raw_report.cmd = ADDR_ACC_X_LSB;
	// XXX PX4DEV transfer((uint8_t *)&raw_report, (uint8_t *)&raw_report, sizeof(raw_report));

	/*
	 * Adjust and scale results to SI units.
	 *
	 * Note that we ignore the "new data" bits.  At any time we read, each
	 * of the axis measurements are the "most recent", even if we've seen
	 * them before.  There is no good way to synchronise with the internal
	 * measurement flow without using the external interrupt.
	 */
	report.timestamp = hrt_absolute_time();
        report.error_count = 0;
	/*
	 * y of board is x of sensor and x of board is -y of sensor
	 * perform only the axis assignment here.
	 * Two non-value bits are discarded directly
	 */
	report.y_raw  = read_reg(ADDR_ACC_X_LSB + 0);
	report.y_raw |= read_reg(ADDR_ACC_X_LSB + 1) << 8;
	report.x_raw  = read_reg(ADDR_ACC_X_LSB + 2);
	report.x_raw |= read_reg(ADDR_ACC_X_LSB + 3) << 8;
	report.z_raw  = read_reg(ADDR_ACC_X_LSB + 4);
	report.z_raw |= read_reg(ADDR_ACC_X_LSB + 5) << 8;

	/* discard two non-value bits in the 16 bit measurement */
	report.x_raw = (report.x_raw / 4);
	report.y_raw = (report.y_raw / 4);
	report.z_raw = (report.z_raw / 4);

	/* invert y axis, due to 14 bit data no overflow can occur in the negation */
	report.y_raw = -report.y_raw;

	report.x = ((report.x_raw * _accel_range_scale) - _accel_scale.x_offset) * _accel_scale.x_scale;
	report.y = ((report.y_raw * _accel_range_scale) - _accel_scale.y_offset) * _accel_scale.y_scale;
	report.z = ((report.z_raw * _accel_range_scale) - _accel_scale.z_offset) * _accel_scale.z_scale;
	report.scaling = _accel_range_scale;
	report.range_m_s2 = _accel_range_m_s2;

	_reports->force(&report);

	/* notify anyone waiting for data */
	poll_notify(POLLIN);

	/* publish for subscribers */
	orb_publish(ORB_ID(sensor_accel), _accel_topic, &report);

	/* stop the perf counter */
	perf_end(_sample_perf);
}
Exemple #18
0
/**
   check for extreme accelerometer values and log to a file on the SD card
 */
void
LSM303D::check_extremes(const accel_report *arb)
{
	const float extreme_threshold = 30;
        static bool boot_ok = false;
	bool is_extreme = (fabsf(arb->x) > extreme_threshold && 
			   fabsf(arb->y) > extreme_threshold && 
			   fabsf(arb->z) > extreme_threshold);
	if (is_extreme) {
		perf_count(_extreme_values);
		// force accel logging on if we see extreme values
		_accel_logging_enabled = true;
	} else {
            boot_ok = true;
        }

	if (! _accel_logging_enabled) {
		// logging has been disabled by user, close
		if (_accel_log_fd != -1) {
			::close(_accel_log_fd);
			_accel_log_fd = -1;
		}
		return;
	}
	if (_accel_log_fd == -1) {
		// keep last 10 logs
		::unlink(ACCEL_LOGFILE ".9");
		for (uint8_t i=8; i>0; i--) {
			uint8_t len = strlen(ACCEL_LOGFILE)+3;
			char log1[len], log2[len];
			snprintf(log1, sizeof(log1), "%s.%u", ACCEL_LOGFILE, (unsigned)i);
			snprintf(log2, sizeof(log2), "%s.%u", ACCEL_LOGFILE, (unsigned)(i+1));
			::rename(log1, log2);
		}
		::rename(ACCEL_LOGFILE, ACCEL_LOGFILE ".1");

		// open the new logfile
		_accel_log_fd = ::open(ACCEL_LOGFILE, O_WRONLY|O_CREAT|O_TRUNC, 0666);
		if (_accel_log_fd == -1) {
			return;
		}
	}

	uint64_t now = hrt_absolute_time();
	// log accels at 1Hz
	if (_last_log_us == 0 ||
	    now - _last_log_us > 1000*1000) {
		_last_log_us = now;
		::dprintf(_accel_log_fd, "ARB %llu %.3f %.3f %.3f %d %d %d boot_ok=%u\r\n",
			  (unsigned long long)arb->timestamp, 
			  arb->x, arb->y, arb->z,
			  (int)arb->x_raw,
			  (int)arb->y_raw,
			  (int)arb->z_raw,
			  (unsigned)boot_ok);
	}

        const uint8_t reglist[] = { ADDR_WHO_AM_I, 0x02, 0x15, ADDR_STATUS_A, ADDR_STATUS_M, ADDR_CTRL_REG0, ADDR_CTRL_REG1, 
                                    ADDR_CTRL_REG2, ADDR_CTRL_REG3, ADDR_CTRL_REG4, ADDR_CTRL_REG5, ADDR_CTRL_REG6, 
                                    ADDR_CTRL_REG7, ADDR_OUT_TEMP_L, ADDR_OUT_TEMP_H, ADDR_INT_CTRL_M, ADDR_INT_SRC_M, 
                                    ADDR_REFERENCE_X, ADDR_REFERENCE_Y, ADDR_REFERENCE_Z, ADDR_OUT_X_L_A, ADDR_OUT_X_H_A, 
                                    ADDR_OUT_Y_L_A, ADDR_OUT_Y_H_A, ADDR_OUT_Z_L_A, ADDR_OUT_Z_H_A, ADDR_FIFO_CTRL, 
                                    ADDR_FIFO_SRC, ADDR_IG_CFG1, ADDR_IG_SRC1, ADDR_IG_THS1, ADDR_IG_DUR1, ADDR_IG_CFG2, 
                                    ADDR_IG_SRC2, ADDR_IG_THS2, ADDR_IG_DUR2, ADDR_CLICK_CFG, ADDR_CLICK_SRC, 
                                    ADDR_CLICK_THS, ADDR_TIME_LIMIT, ADDR_TIME_LATENCY, ADDR_TIME_WINDOW, 
                                    ADDR_ACT_THS, ADDR_ACT_DUR,
                                    ADDR_OUT_X_L_M, ADDR_OUT_X_H_M, 
                                    ADDR_OUT_Y_L_M, ADDR_OUT_Y_H_M, ADDR_OUT_Z_L_M, ADDR_OUT_Z_H_M, 0x02, 0x15, ADDR_WHO_AM_I};
        uint8_t regval[sizeof(reglist)];
        for (uint8_t i=0; i<sizeof(reglist); i++) {
            regval[i] = read_reg(reglist[i]);
        }

	// log registers at 10Hz when we have extreme values, or 0.5 Hz without
	if (_last_log_reg_us == 0 ||
	    (is_extreme && (now - _last_log_reg_us > 250*1000)) ||
	    (now - _last_log_reg_us > 10*1000*1000)) {
		_last_log_reg_us = now;
		::dprintf(_accel_log_fd, "XREG %llu", (unsigned long long)hrt_absolute_time());
		for (uint8_t i=0; i<sizeof(reglist); i++) {
			::dprintf(_accel_log_fd, " %02x:%02x", (unsigned)reglist[i], (unsigned)regval[i]);
		}
		::dprintf(_accel_log_fd, "\n");
	}

	// fsync at 0.1Hz
	if (now - _last_log_sync_us > 10*1000*1000) {
		_last_log_sync_us = now;
		::fsync(_accel_log_fd);
	}

	// play alarm every 10s if we have had an extreme value
	if (perf_event_count(_extreme_values) != 0 && 
	    (now - _last_log_alarm_us > 10*1000*1000)) {
		_last_log_alarm_us = now;
		int tfd = ::open(TONEALARM_DEVICE_PATH, 0);
		if (tfd != -1) {
			uint8_t tone = 3;
			if (!is_extreme) {
				tone = 3;
			} else if (boot_ok) {
				tone = 4;
			} else {
				tone = 5;
			}
			::ioctl(tfd, TONE_SET_ALARM, tone);
			::close(tfd);
		}		
	}
}
Exemple #19
0
int MPU9250::reset_mpu()
{
	uint8_t retries;

	switch (_whoami) {
	case MPU_WHOAMI_9250:
	case MPU_WHOAMI_6500:
		write_reg(MPUREG_PWR_MGMT_1, BIT_H_RESET);
		write_checked_reg(MPUREG_PWR_MGMT_1, MPU_CLK_SEL_AUTO);
		write_checked_reg(MPUREG_PWR_MGMT_2, 0);
		usleep(1000);
		break;
	}

	// Enable I2C bus or Disable I2C bus (recommended on data sheet)
	write_checked_reg(MPUREG_USER_CTRL, is_i2c() ? 0 : BIT_I2C_IF_DIS);

	// SAMPLE RATE
	_set_sample_rate(_sample_rate);

	_set_dlpf_filter(MPU9250_DEFAULT_ONCHIP_FILTER_FREQ);

	// Gyro scale 2000 deg/s ()
	switch (_whoami) {
	case MPU_WHOAMI_9250:
	case MPU_WHOAMI_6500:
		write_checked_reg(MPUREG_GYRO_CONFIG, BITS_FS_2000DPS);
		break;
	}


	// correct gyro scale factors
	// scale to rad/s in SI units
	// 2000 deg/s = (2000/180)*PI = 34.906585 rad/s
	// scaling factor:
	// 1/(2^15)*(2000/180)*PI
	_gyro_range_scale = (0.0174532 / 16.4);//1.0f / (32768.0f * (2000.0f / 180.0f) * M_PI_F);
	_gyro_range_rad_s = (2000.0f / 180.0f) * M_PI_F;

	set_accel_range(ACCEL_RANGE_G);

	// INT CFG => Interrupt on Data Ready
	write_checked_reg(MPUREG_INT_ENABLE, BIT_RAW_RDY_EN);        // INT: Raw data ready

#ifdef USE_I2C
	bool bypass = !_mag->is_passthrough();
#else
	bool bypass = false;
#endif

	/* INT: Clear on any read.
	 * If this instance is for a device is on I2C bus the Mag will have an i2c interface
	 * that it will use to access the either: a) the internal mag device on the internal I2C bus
	 * or b) it could be used to access a downstream I2C devices connected to the chip on
	 * it's AUX_{ASD|SCL} pins. In either case we need to disconnect (bypass) the internal master
	 * controller that chip provides as a SPI to I2C bridge.
	 * so bypass is true if the mag has an i2c non null interfaces.
	 */

	write_checked_reg(MPUREG_INT_PIN_CFG, BIT_INT_ANYRD_2CLEAR | (bypass ? BIT_INT_BYPASS_EN : 0));

	write_checked_reg(MPUREG_ACCEL_CONFIG2, BITS_ACCEL_CONFIG2_41HZ);

	retries = 3;
	bool all_ok = false;

	while (!all_ok && retries--) {

		// Assume all checked values are as expected
		all_ok = true;
		uint8_t reg;
		uint8_t bankcheck = 0;

		for (uint8_t i = 0; i < _num_checked_registers; i++) {
			if ((reg = read_reg(_checked_registers[i])) != _checked_values[i]) {

				write_reg(_checked_registers[i], _checked_values[i]);
				PX4_ERR("Reg %d is:%d s/b:%d Tries:%d - bank s/b %d, is %d", _checked_registers[i], reg, _checked_values[i], retries,
					REG_BANK(_checked_registers[i]), bankcheck);
				all_ok = false;
			}
		}
	}

	return all_ok ? OK : -EIO;
}
Exemple #20
0
int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg)
{
	struct v4l2_tuner *tuner = arg;
	struct v4l2_control *ctrl = arg;
	struct v4l2_routing *route = arg;
	u16 mask, data;

	switch (command) {
	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
		mask = itv->card->gpio_audio_freq.mask;
		switch (*(u32 *)arg) {
		case 32000:
			data = itv->card->gpio_audio_freq.f32000;
			break;
		case 44100:
			data = itv->card->gpio_audio_freq.f44100;
			break;
		case 48000:
		default:
			data = itv->card->gpio_audio_freq.f48000;
			break;
		}
		break;

	case VIDIOC_G_TUNER:
		mask = itv->card->gpio_audio_detect.mask;
		if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask))
			tuner->rxsubchans = V4L2_TUNER_MODE_STEREO |
			       V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
		else
			tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
		return 0;

	case VIDIOC_S_TUNER:
		mask = itv->card->gpio_audio_mode.mask;
		switch (tuner->audmode) {
		case V4L2_TUNER_MODE_LANG1:
			data = itv->card->gpio_audio_mode.lang1;
			break;
		case V4L2_TUNER_MODE_LANG2:
			data = itv->card->gpio_audio_mode.lang2;
			break;
		case V4L2_TUNER_MODE_MONO:
			data = itv->card->gpio_audio_mode.mono;
			break;
		case V4L2_TUNER_MODE_STEREO:
		case V4L2_TUNER_MODE_LANG1_LANG2:
		default:
			data = itv->card->gpio_audio_mode.stereo;
			break;
		}
		break;

	case AUDC_SET_RADIO:
		mask = itv->card->gpio_audio_input.mask;
		data = itv->card->gpio_audio_input.radio;
		break;

	case VIDIOC_S_STD:
		mask = itv->card->gpio_audio_input.mask;
		data = itv->card->gpio_audio_input.tuner;
		break;

	case VIDIOC_INT_S_AUDIO_ROUTING:
		if (route->input > 2)
			return -EINVAL;
		mask = itv->card->gpio_audio_input.mask;
		switch (route->input) {
			case 0:
				data = itv->card->gpio_audio_input.tuner;
				break;
			case 1:
				data = itv->card->gpio_audio_input.linein;
				break;
			case 2:
			default:
				data = itv->card->gpio_audio_input.radio;
				break;
		}
		break;

	case VIDIOC_G_CTRL:
		if (ctrl->id != V4L2_CID_AUDIO_MUTE)
			return -EINVAL;
		mask = itv->card->gpio_audio_mute.mask;
		data = itv->card->gpio_audio_mute.mute;
		ctrl->value = (read_reg(IVTV_REG_GPIO_OUT) & mask) == data;
		return 0;

	case VIDIOC_S_CTRL:
		if (ctrl->id != V4L2_CID_AUDIO_MUTE)
			return -EINVAL;
		mask = itv->card->gpio_audio_mute.mask;
		data = ctrl->value ? itv->card->gpio_audio_mute.mute : 0;
		break;

	case VIDIOC_QUERYCTRL:
	{
		struct v4l2_queryctrl *qc = arg;

		if (qc->id != V4L2_CID_AUDIO_MUTE)
			return -EINVAL;
		*qc = gpio_ctrl_mute;
		return 0;
	}

	case VIDIOC_LOG_STATUS:
		IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n",
			read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT),
			read_reg(IVTV_REG_GPIO_IN));
		return 0;

	case VIDIOC_INT_S_VIDEO_ROUTING:
		if (route->input > 2) /* 0:Tuner 1:Composite 2:S-Video */
			return -EINVAL;
		mask = itv->card->gpio_video_input.mask;
		if  (route->input == 0)
			data = itv->card->gpio_video_input.tuner;
		else if  (route->input == 1)
			data = itv->card->gpio_video_input.composite;
		else
			data = itv->card->gpio_video_input.svideo;
		break;

	default:
		return -EINVAL;
	}
	if (mask)
		write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
	return 0;
}
Exemple #21
0
int AK8975::check_calibration()
{
	uint8_t data[6] = {0,0,0,0,0,0};
	uint8_t cmd = 0;
	int retries = 10;
	int i, ret;
	float xdata, ydata, zdata;

	/* manual polling */
	stop();
	_measure_ticks = 0;
//	if (OK != ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_MANUAL))
//		errx(1, "failed to set manual poll rate");

	/* set to power down mode */
	ret = write_reg(ADDR_MODE, AK8975_MODE_POWERDWN);
	if (OK != ret) {
		perf_count(_comms_errors);
		debug("Couldn't enter power down mode");
	}
	usleep(200);

	/* write "1" to self bit of ASTC register */
	ret = write_reg(ADDR_ASTC, SET_REG_SELF_TEST);
	if (OK != ret) {
		perf_count(_comms_errors);
		debug("Couldn't write self test bit");
	}

	/* enter self test mode */
	ret = write_reg(ADDR_MODE, AK8975_MODE_TEST);
	if (OK != ret) {
		perf_count(_comms_errors);
		debug("Couldn't enter test mode");
	}

	/* wait for data ready bit */
	for (i=0;i<retries;i++) {
		usleep(200);
		if (read_reg(ADDR_DRDY, data[0])) {
			perf_count(_comms_errors);
			debug("data ready read error");
			continue;
		}
		if (!(data[0] & STATUS_REG_DATA_READY)) {
			/* data not ready */
			debug("data not ready [%02X]", data[0]);
			continue;
		}
		break;
	}

	/* data read errors */
	if (i == retries) 
		errx(1, "test calibration failed, too many read tries");

	/* read the data */
	/* get measurements from the device */
	cmd = ADDR_DATA_OUT_X_LSB;
	ret = transfer(&cmd, 1, data, 6);

	if (ret != OK) {
		perf_count(_comms_errors);
		debug("data/status read error");
		errx(1, "calibration data read failure");
	}

	/* write "0" to self bit of ASTC register */
	ret = write_reg(ADDR_ASTC, 0);
	if (OK != ret) {
		perf_count(_comms_errors);
		debug("Couldn't clear self test bit");
	}

	/* apply sensitivity adjustment */
	xdata = ((float)((int16_t)(data[0]+(data[1]<<8))))*_scale.x_scale;
	ydata = ((float)((int16_t)(data[2]+(data[3]<<8))))*_scale.y_scale;
	zdata = ((float)((int16_t)(data[4]+(data[5]<<8))))*_scale.z_scale;
	debug("calibration readings = [%.3f,%.3f,%.3f]", (double)xdata,(double)ydata,(double)zdata);

	/* return true or false if in proper range */
	return ((xdata<=100)&&(xdata>=-100)&&(ydata<=100)&&(ydata>=-100)&&(zdata<=-300)&&(zdata>=-1000));
}
Exemple #22
0
int MPU9250::reset()
{
	write_reg(MPUREG_PWR_MGMT_1, BIT_H_RESET);
	up_udelay(10000);

	write_checked_reg(MPUREG_PWR_MGMT_1, MPU_CLK_SEL_AUTO);
	up_udelay(1000);

	write_checked_reg(MPUREG_PWR_MGMT_2, 0);
	up_udelay(1000);

	// SAMPLE RATE
	_set_sample_rate(_sample_rate);
	usleep(1000);

	// FS & DLPF   FS=2000 deg/s, DLPF = 20Hz (low pass filter)
	// was 90 Hz, but this ruins quality and does not improve the
	// system response
	_set_dlpf_filter(MPU9250_DEFAULT_ONCHIP_FILTER_FREQ);
	usleep(1000);

	// Gyro scale 2000 deg/s ()
	write_checked_reg(MPUREG_GYRO_CONFIG, BITS_FS_2000DPS);
	usleep(1000);

	// correct gyro scale factors
	// scale to rad/s in SI units
	// 2000 deg/s = (2000/180)*PI = 34.906585 rad/s
	// scaling factor:
	// 1/(2^15)*(2000/180)*PI
	_gyro_range_scale = (0.0174532 / 16.4);//1.0f / (32768.0f * (2000.0f / 180.0f) * M_PI_F);
	_gyro_range_rad_s = (2000.0f / 180.0f) * M_PI_F;

	set_accel_range(16);

	usleep(1000);

	// INT CFG => Interrupt on Data Ready
	write_checked_reg(MPUREG_INT_ENABLE, BIT_RAW_RDY_EN);        // INT: Raw data ready
	usleep(1000);
	write_checked_reg(MPUREG_INT_PIN_CFG, BIT_INT_ANYRD_2CLEAR); // INT: Clear on any read
	usleep(1000);

	uint8_t retries = 10;

	while (retries--) {
		bool all_ok = true;

		for (uint8_t i = 0; i < MPU9250_NUM_CHECKED_REGISTERS; i++) {
			if (read_reg(_checked_registers[i]) != _checked_values[i]) {
				write_reg(_checked_registers[i], _checked_values[i]);
				all_ok = false;
			}
		}

		if (all_ok) {
			break;
		}
	}

	return OK;
}
Exemple #23
0
/*Reading the X,Y,Z axes values of the gyroscope*/
void readGyro_XYZ(void)
{
	unsigned char xlow=0, xhigh = 0, ylow=0, yhigh=0, zlow=0, zhigh=0;

	float elapsedTime;

	/*The angular velocity values of the gyroscope along X, Y and Z axes are 16 bit values*/
	/*The values range from 0 to 65535. The positive angular velocity values are from 0 to 32767*/
	/*The values from 32767 to 65535 are negative*/


	xlow = read_reg(gyro_slvAddr,OUT_X_Lo);
	xhigh = read_reg(gyro_slvAddr,OUT_X_Hi);
	
	ylow = read_reg(gyro_slvAddr,OUT_Y_Lo);
	yhigh = read_reg(gyro_slvAddr,OUT_Y_Hi);
	
	zlow = read_reg(gyro_slvAddr,OUT_Z_Lo);
	zhigh = read_reg(gyro_slvAddr,OUT_Z_Hi);

	/*Obtain the timestamp when the X,Y, Z gyro values are read*/
	clock_gettime(CLOCK_MONOTONIC,&gyro_time);
	
	/*Concatenate the LSB and MSB values of the X, Y and Z register values of the gyroscope to obtain the 12 bi value*/
	raw_x = (xhigh << 8) + xlow;
	raw_y = (yhigh << 8) + ylow;
	raw_z = (zhigh << 8) + zlow;
	

	/*Since we are considering only the horizontal movement of the PCB, we are considering only the X axis values of the Gyroscope*/
	/*The values read from the X, Y and Z registers of the Gyroscope are in 2's complement form.*/
	/*The following algorithm converts the gyroscope values in the -250dps to +250dps range*/	

	if(raw_x > 0x7FFF)
	{
		raw_x = -(raw_x - 0x7FFF) + 1;
	}
	else
	{
		raw_x = raw_x;
	}
	
	if(raw_y > 0x7FFF)
	{
		raw_y = -(raw_y - 0x7FFF) + 1;
		ytotal = raw_y * (8.75f/1000);
	}
	else
	{
		raw_y = raw_y;
		ytotal = raw_y * (8.75f/1000);
	}
	if(raw_z > 0x7FFF)
	{
		raw_z = -(raw_z - 0x7FFF) + 1;
		ztotal = raw_z * (8.75f/1000);
	}
	else
	{
		raw_z = raw_z;
		ztotal = raw_z * (8.75f/1000);
	}


	/*Note : The sensitivity for 250 dps is 8.75 mdps/digit*/

	
}
Exemple #24
0
void dump_reg(void)
{
    u32 val = 0;

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_VND_IDL);
    printk("Provides unique vendor identification through I2C  Default:0x01(Low)\n");
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_DEV_IDL);
    printk("Provides unique device type identification through I2C.  Default:0x36 (Low)\n");
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_DEV_IDH);
    printk("Provides unique device type identification through I2C.  Default:0x97 (High)\n");
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_DEV_REV);
    printk("Allows distinction between revisions of same device.  Default:0x00\n");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_SRST);
    DUMPREGVAL(val, HDMI_CORE_SYS_SRST);
    DUMPONEBIT(BIT_0, val, "0 = Normal Operation", "1 = Reset all sections, including audio FIFO, but not writable registers or HDCP", "SWRST; Software reset");
    DUMPONEBIT(BIT_1, val, "0 = Normal Operation", "1 = Reset (flush) audio FIFO", "FIFORST; Audio FIFO reset");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_CTRL1);
    DUMPREGVAL(val, HDMI_CORE_CTRL1);
    DUMPONEBIT(BIT_0, val, "When LOW, interrupts are in power-down mode.", "HIGH is normal operation.", "Power down mode");
    DUMPONEBIT(BIT_1, val, "0 = Latch Input on Falling Edge", "1 = Latch Input on Rising Edge", "Edge select");
    DUMPONEBIT(BIT_2, val, "0 = 12-bit", "1 = 24-bit", "Input bus select");
    DUMPONEBIT(BIT_4, val, "0 = Fixed LOW", "1 = Follow VSYNC input", "HSYNC enable");
    DUMPONEBIT(BIT_5, val, "0 = Fixed LOW", "1 = Follow VSYNC input", "VSYNC enable");
    DUMPBITLOG(BIT_6, val, "The current status of the VSYNC input pin. Refer to the INTR2 register (0x72:0x72), described on page 30, for an interrupt tied to VSYNC active edge.");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_SYS_STAT);
    DUMPREGVAL(val, HDMI_CORE_SYS_SYS_STAT);
    DUMPBITLOG(BIT_0, val, "IDCK (io_pclkpin) to TMDS clock (v_ck2x) is stable and the Transmitter can send reliable data on the TMDS link. A change to the IDCK sets this bit LOW. After a subsequent LOW to HIGH transition, indicating a stable input clock, a software reset is recommended.");
    DUMPBITLOG(BIT_1, val, "Hot Plug Detect: The state of the Hot Plug Detect pin can be read here.");
    DUMPONEBIT(BIT_2, val, "0 = No Receiver connected", "1 = Receiver is connected and powered on", "Receiver Sense (works in DC-coupled systems only)");
    DUMPBITLOG(BIT_7, val, "VREF mode. Always HIGH");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_DATA_CTRL);
    DUMPREGVAL(val, HDMI_CORE_SYS_DATA_CTRL);
    DUMPONEBIT(BIT_0, val, "When connected to 1b0, enables firmware to take the decision whether to send unencrypted data or not.", "By connecting to 1b1, HDMI Tx will be able to send ONLY encrypted data.", "This register gets the value of the pin io_hdcp_sel.");
    DUMPONEBIT(BIT_1, val, "0 = Do not send zeros in audio packet", "1 = Send zeros in audio packet", "AUD_MUTE");
    DUMPONEBIT(BIT_2, val, "0 = No Receiver connected", "1 = Receiver is connected and powered on", "Receiver Sense (works in DC-coupled systems only)");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_VID_CTRL);
    DUMPREGVAL(val, HDMI_CORE_SYS_VID_CTRL);
    DUMPBITS(BIT_1, BIT_0, val, "Clock mode:\n 0b00 = Pixel data is not replicated\n 0b01 = Pixels are replicated once (each sent twice)\n 0b10 = RSVD\n 0b11 = Pixels are replicated 4 times (each sent four times)");
    DUMPONEBIT(BIT_4, val, "0 = BT.601 conversion", "1 = BT.709 conversion", "Color Space Conversion Standard select");
    DUMPONEBIT(BIT_5, val, "0 = All 8-bit input modes", "1 = All 12-bit 4:2:2 input modes", "Extended Bit mode");
    DUMPBITLOG(BIT_6, val, "Do not write this bit to 1.");
    DUMPONEBIT(BIT_7, val, "0 = Do not invert field bit","1 = Invert field bit", "Invert field polarity");


    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_VID_ACEN);
    DUMPREGVAL(val, HDMI_CORE_SYS_VID_ACEN);
    DUMPONEBIT(BIT_0, val, "0 = Disabled", "1 = Enabled", "Enable down sampler 4:4:4 to 4:2:2");
    DUMPONEBIT(BIT_1, val, "0 = Disabled", "1 = Enabled", "Enable Range Compress 0-255 to 16-234");
    DUMPONEBIT(BIT_2, val, "0 = Disabled", "1 = Enabled", "Enable RGB to YCbCr color-space converter");
    DUMPONEBIT(BIT_3, val, "0 = Disabled", "1 = Enabled", "Enable Range Clip from 16 to 235 (RGB and Y)/ 240 (CbCr)");
    DUMPONEBIT(BIT_4, val, "0 = Output color space is RGB", "1 = Output color space is YCbCr", "Identifies the output color space on the link - used by the Clipper block to determine which way to clip");
    DUMPBITS(BIT_7, BIT_6, val, "Identifies the number of bits per input video channel: \n 0b00 = 8 bits per channel or 24-bit bus mode \n 0b01 = 10 bits per channel or 30-bit bus mode\n 0b10 = 12 bits per channel or 36-bit bus mode\n 0b11 = Reserved");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_VID_MODE);
    DUMPREGVAL(val, HDMI_CORE_SYS_VID_MODE);
    DUMPONEBIT(BIT_0, val, "0 = Disabled", "1 = Enabled", "Embedded Sync Extraction");
    DUMPONEBIT(BIT_1, val, "0 = Disabled", "1 = Enabled", "One- to Two-Data-Channel Demux");
    DUMPONEBIT(BIT_2, val, "0 = Disabled", "1 = Enabled", "Upsampling 4:2:2 to 4:4:4");
    DUMPONEBIT(BIT_3, val, "0 = Disabled", "1 = Enabled", "YcbCr to RGB Color Space Conversion");
    DUMPONEBIT(BIT_4, val, "0 = Disabled", "1 = Enabled", "Data Range 16-to-235 to 0-to-255 expansion");
    DUMPONEBIT(BIT_5, val, "0 = Dither disabled", "1 = Dither enabled", "the video output is truncated to the output width specified in DITHER_MODE [7:6]");
    DUMPBITS(BIT_7, BIT_6, val, "Identifies the number of bits per output video channel: \n 0b00 = Dither to 8 bits\n 0b01 = Dither to 10 bits\n 0b10 = Dither to 12 bits\n 0b11 = Reserved");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_INTR_STATE);
    DUMPREGVAL(val, HDMI_CORE_SYS_INTR_STATE);
    DUMPBITLOG(BIT_7, val, "Interrupt State. When an interrupt is asserted, this bit is set to 1. The polarity of the INT output signal is set using this bit and the POLARITY# bit in the INT_CTRL register (0x72:0x79). Only INTR1, INTR2, INTR3, and INTR4 bits with matching set bits in INT_UNMASK can contribute to setting the INTR bit.");


    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_INTR1);
    DUMPREGVAL(val, HDMI_CORE_SYS_INTR1);
    DUMPBITLOG(BIT_0, val, "Audio FIFO Underflow.\n Similar to OVER_RUN. This interrupt occurs when the audio FIFO empties");
    DUMPBITLOG(BIT_1, val, "Audio FIFO Overflow.\n This interrupt occurs if the audio FIFO overflows when more samples are written into it than are drawn out across the HDMI link. Such a condition can occur from a transient change in the Fs or pixel clock rate.");
    DUMPBITLOG(BIT_2, val, "Input counted past frame count threshold set in RI_128_COMP register.\n This interrupt occurs when the count written to register 0x72:0x24 is matched by the VSYNC (frame) counter in the HDMI Transmitter. It should trigger the firmware to perform a link integrity check. Such a match occurs every 128 frames.");
    DUMPBITLOG(BIT_3, val, "Input S/PDIF stream has bi-phase error. This can occur when there is noise or an Fs rate change on the S/PDIF input.");
    DUMPBITLOG(BIT_4, val, "New preamble forced to drop sample (S/PDIF input only). \n If the HDMI Transmitter detects an 8-bit preamble in the S/PDIF input stream before the subframe has been captured, this interrupt is set. A S/PDIF input that stops signaling or a flat line condition can create such a premature preamble.");
    DUMPBITLOG(BIT_5, val, "Receiver Sense Interrupt asserted if RSEN has changed. \n This interrupt is set whenever VCC is applied to, or removed from, the attached HDMI Receiver chip. A Receiver with multiple input ports can also disconnect the TMDS termination to the unused port, which triggers this RSEN interrupt.");
    DUMPBITLOG(BIT_6, val, "Monitor Detect Interrupt - asserted if Hot Plug Detect has changed state. \n The HDMI Transmitter signals a change in the connectivity to a Sink, either unplug or plug. HDMI specifies that Hot Plug be active only when the Sinks EDID is ready to be read and that Hot Plug be toggled any time there is a change in connectivity downstream of an attached Repeater.");
    DUMPBITLOG(BIT_7, val, "Software Induced Interrupt - allows the firmware to generate an interrupt directly.");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_INTR2);
    DUMPREGVAL(val, HDMI_CORE_SYS_INTR2);
    DUMPBITLOG(BIT_0, val, "Asserted when VSYNC active edge is recognized. It is useful for triggering firmware actions that occur during vertical blanking.");
    DUMPBITLOG(BIT_1, val, "TCLK_STABLE (register 0x72:0x09[0]) changes state. \n Whenever IDCK changes, there is a temporary instability in the internal clocking. This interrupt is set when the internal clocking has stabilized.");
    DUMPBITLOG(BIT_2, val, "ACR Packet Overwrite. \n This interrupt occurs if the HDMI Transmitter puts a NCTS packet into the queue before the previous NCTS packet has been sent. This can happen if very long active data times do not allow for sufficient NCTS packet bandwidth. For all CEA-861D modes, no ACR_OVR interrupt should occur.");
    DUMPBITLOG(BIT_3, val, "S/PDIF Parity Error. \n The S/PDIF stream includes a parity (P) bit at the end of each sub-frame. An interrupt occurs if the calculated parity does not match the state of this bit.");
    DUMPBITLOG(BIT_4, val, "This condition is the opposite of the condition that causes DROP_SAMPLE (0x72:0x71[4]). This interrupt occurs if a preamble is expected but not found when decoding the S/PDIF stream.");
    DUMPBITLOG(BIT_5, val, "The ENC_EN bit (0x72.0x0F[0]) changed from 1 to 0. \n This interrupt occurs if encryption is turned off.");
    DUMPBITLOG(BIT_6, val, "S/PDIF Parity Error. \n The S/PDIF stream includes a parity (P) bit at the end of each sub-frame. An interrupt occurs if the calculated parity does not match the state of this bit.");
    DUMPBITLOG(BIT_7, val, "If set, this interrupt detected that the FIFORDY bit (0x74:0x40[5]) is set to 1.");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_INTR3);
    DUMPREGVAL(val, HDMI_CORE_SYS_INTR3);
    DUMPBITLOG(BIT_0, val, "DDC FIFO is empty.");
    DUMPBITLOG(BIT_1, val, "DDC FIFO is full.");
    DUMPBITLOG(BIT_2, val, "DDC FIFO is half full.");
    DUMPBITLOG(BIT_3, val, "DDC command is complete.");
    DUMPBITLOG(BIT_4, val, "Ri and Ri do not match during frame #127 (ICNT 每1).");
    DUMPBITLOG(BIT_5, val, "Ri and Ri do not match during frame #0 (ICNT).");
    DUMPBITLOG(BIT_6, val, "Ri did not change between frame #127 and #0.");
    DUMPBITLOG(BIT_7, val, "Ri not read within one frame.");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_INTR4);
    DUMPREGVAL(val, HDMI_CORE_SYS_INTR4);
    DUMPBITLOG(BIT_0, val, "DSD stream got invalid sequence: more then 24 bits of the same value. Asserted if set to 1. Write 1 to clear");
    DUMPBITLOG(BIT_1, val, "reg_intr4_stat1");
    DUMPBITLOG(BIT_2, val, "reg_intr4_stat2");
    DUMPBITLOG(BIT_3, val, "reg_intr4_stat3 CEC interrupt");

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_INTR1_MASK);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_INTR2_MASK);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_INTR3_MASK);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_INTR4_MASK);
    printk("Each bit corresponds to one bit in INTR1, INTR2, INTR3, or INTR4: \n 0 = Disable corresponding interrupt from INT output \n 1 = Enable corresponding interrupt to INT output\n");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_TMDS_CTRL);
    DUMPREGVAL(val, HDMI_CORE_SYS_TMDS_CTRL);
    DUMPONEBIT(BIT_0, val, "0 = Disable", "1 = Enable", "Internal source termination");
    DUMPBITLOG(BIT_1, val, "1: BGR output is connected to ext_swing pin");
    DUMPBITS(BIT_3, BIT_2, val, "Output Swing Control \n 11: -18% \n 10: -9% \n 01: 0% \n 00: +9%");
    DUMPBITS(BIT_6, BIT_5, val, "Selects FPLL multiple of the IDCK: \n 0b00 = FPLL is 0.5*IDCK \n 0b01 = FPLL is 1.0*IDCK \n 0b10 = FPLL is 2.0*IDCK \n 0b11 = FPLL is 4.0*IDCK");

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_HDCP_CTRL);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_HDCP_BKSV_ADDR);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_HDCP_AN_ADDR);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_HDCP_AKSV_ADDR);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_HDCP_Ri_ADDR);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_HDCP_RI_STAT);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_HDCP_RI_CMD_ADDR);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_HDCP_RI_START);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_HDCP_RI_RX_1);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_HDCP_RI_RX_2);

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_DLY);
    printk("Width of the area to the left of the active display. The unit of measure is pixels. This register should be set to the sum of (HSYNC width) + (horizontal back porch) + (horizontal left border), and is used only for DE generation. \n Note: This 12-bit value includes four bits from register 0x72:0x33. \n The valid range is 1-4095. 0 is invalid.\n");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_CTRL);
    DUMPREGVAL(val, HDMI_CORE_SYS_DE_CTRL);
    DUMPONEBIT(BIT_4, val, "0 = Positive polarity (leading edge rises).", "1 = Negative polarity (leading edge falls).", "HSYNC polarity");
    DUMPONEBIT(BIT_5, val, "0 = Positive polarity (leading edge rises).", "1 = Negative polarity (leading edge falls).", "VSYNC polarity");
    DUMPONEBIT(BIT_6, val, "0 = Disabled", "1 = Enabled", "Generate DE signal");

    val = FLD_GET(read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_CTRL), 3, 0) << BIT_MAX;
    val &= read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_DLY);
    printk("Bits 11:8 of the DE_DLY value (see register 0x72:0x32). value = %d", val);


    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_TOP);
    printk("Defines the height of the area above the active display. The unit of measure is lines (HSYNC pulses). This register should be set to the sum of (VSYNC width) + (vertical back porch) + (vertical top border). \n The valid range is 1-127. 0 is invalid.\n");

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_CNTL);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_CNTH);
    printk("Bits 11:0 Defines the width of the active display. The unit of measure is pixels. This register should be set to the desired horizontal resolution.\n The valid range is 1-4095. 0 is invalid.\n");
    val = FLD_GET(read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_CNTH), 3, 0) << BIT_MAX;
    val &= read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_CNTL);
    printk("Bits 11:0 val=%d\n", val);

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_LINL);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_LINH_1);
    printk("Bits 10:0 Defines the height of the active display. The unit of measure is lines (HSYNC pulses). Set this register to the desired vertical resolution. For interlaced modes, set this register to the number of lines per field, which is half the overall vertical resolution. \n The valid range is 1-2047. 0 is invalid.\n");
    val = FLD_GET(read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_LINH_1), 2, 0) << BIT_MAX;
    val &= read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_DE_LINL);
    printk("Bits 10:0 val=%d\n", val);

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_INT_CNTRL);
    DUMPREGVAL(val, HDMI_CORE_SYS_INT_CNTRL);
    DUMPONEBIT(BIT_1, val, "0 = Assert HIGH", "1 = Assert LOW", "Set software interrupt");
    DUMPONEBIT(BIT_2, val, "0 = Push/Pull", "1 = Open Drain pin", "INT pin output type");
    DUMPONEBIT(BIT_3, val, "0 = Clear interrupt", "1 = Set interrupt", "INT pin assertion level");

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_SYS_VID_BLANK1);

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_DDC_CMD);
    DUMPREGVAL(val, HDMI_CORE_DDC_CMD);
    DUMPBITLOG(BIT_3, val, "DDC command: \n 0b1111 = Abort Transaction \n 0b1001 = Clear FIFO \n 0b1010 = Clock SCL \n 0b0000 = Current Address Read with no ACK on last byte \n 0b0010 = Sequential Read with no ACK on last byte \n 0b0100 = Enhanced DDC Read with no ACK on last byte \n 0b0110 = Sequential Write ignoring ACK on last byte \n 0b0111 = Sequential Write requiring ACK on last byte \n Writing to this register immediately initiates the I2C transaction on the DDC bus.");
    DUMPONEBIT(BIT_4, val, "0 = Enabled", "1 = Disabled", "Enable 3ns glitch filtering on the DDC clock and data line");
    DUMPONEBIT(BIT_5, val, "0 = Enabled", "1 = Disabled", "Enable the DDC delay");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_DDC_STATUS);
    DUMPREGVAL(val, HDMI_CORE_DDC_STATUS);
    DUMPBITLOG(BIT_0, val, "1 = DDC FIFO Write In Use");
    DUMPBITLOG(BIT_1, val, "1 = DDC FIFO Read In Use");
    DUMPBITLOG(BIT_2, val, "1 = DDC FIFO Empty");
    DUMPBITLOG(BIT_3, val, "1 = DDC FIFO Full");
    DUMPBITLOG(BIT_4, val, "1 = DDC operation in progress");
    DUMPBITLOG(BIT_5, val, "1 = HDMI Transmitter did not receive an ACK from slave device during address or data write");
    DUMPBITLOG(BIT_6, val, "1 = I2C transaction did not start because I2C bus is pulled LOW by an external device");

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_DDC_ADDR);
    printk("Bits 7:1 DDC device address\n");

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_DDC_SEGM);
    printk("Bits 7:0 DDC segment address\n");

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_DDC_OFFSET);
    printk("Bits 7:0 DDC offset address\n");

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_DDC_COUNT1);
    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_DDC_COUNT2);
    printk("Bits 9:0 The total number of bytes to be read from the slave or written to the slave before a Stop bit is sent on the DDC bus. For example, if the HDCP KSV FIFO length is 635 bytes (127 devices x 5 bytes/KSV), the DDC_COUNT must be 0x27B\n");
    val = FLD_GET(read_reg(HDMI_CORE_SYS, HDMI_CORE_DDC_COUNT2), 1, 0) << BIT_MAX;
    val &= read_reg(HDMI_CORE_SYS, HDMI_CORE_DDC_COUNT1);
    printk("Bits 9:0 val=%d\n", val);

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_DDC_DATA);
    printk("Bits 7:0 DDC data input\n");

    DUMPREG(HDMI_CORE_SYS, HDMI_CORE_DDC_FIFOCNT);
    printk("Bits 7:0 FIFO data byte count (the number of bytes in the FIFO). \n The DDC FIFO size is 16. The maximum value for DDC_FIFOCNT is 0x10\n");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_SHA_CONTROL);
    DUMPREGVAL(val, HDMI_CORE_SYS_SHA_CONTROL);
    DUMPBITLOG(BIT_0, val, "Firmware starts the SHA generation by writing ※1§; which generates 1 clock strobe. If &1 is written, the state is inverted.");
    DUMPBITLOG(BIT_1, val, "If 1, means that SHA picked up the \"SHA go stat\" command.");
    DUMPONEBIT(BIT_2, val, "0 - regular mode", "1 - select SHA debug mode when firmware can overwrite the M0.", "Selects SHA mode");
    DUMPONEBIT(BIT_3, val, "0 = M0 internal mode (M0 non-reable over I2C)", "1 = M0 external mode (M0 readable over I2C)", "M0 mode");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_RI_CMD);
    DUMPREGVAL(val, HDMI_CORE_SYS_RI_CMD);
    DUMPONEBIT(BIT_0, val, "0 = Disabled", "1 = Enabled", "Enable Ri check. Check bit 0 of the Ri_STAT register (0x72:0x26) for firmware and hardware DDC control handshaking");
    DUMPONEBIT(BIT_1, val, "0 = Disable", "1 = Enable", "Enable polling of the BCAP_DONE bit (0x72:0x72[7]) \n Note: To poll the BCAP_DONE bit, the ENC_EN (0x72:0x0F[0]) bit and the Ri_EN bit must be enabled on the HDMI Transmitter");

    val = read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS_EPCM);
    DUMPREGVAL(val, HDMI_CORE_SYS_EPCM);
    DUMPBITLOG(BIT_4, val, "Command: \n 0b00011 = Run all BIST tests \n 0b00100 = Run only CRC test \n 0b01000 = Run only BIST self authentication test 1 \n 0b10000 = Run only BIST self authentication test 2 \n All other values are reserved. \n Before writing a new value into this register, verify that the previous command is complete by checking the 0x72.0xF9[0] register.");
    DUMPBITLOG(BIT_5, val, "1 = Enable loading of KSV from OTP \n Write 0 before enabling again.");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_ACR_CTRL);
    DUMPREGVAL(val, HDMI_CORE_AV_ACR_CTRL);
    DUMPONEBIT(BIT_0, val, "0 = Send HW-updated CTS value in N/CTS packet (recommended)", "1 = Send SW-updated CTS value in N/CTS packet (for diagnostic use)", "CTS Source Select:");
    DUMPONEBIT(BIT_1, val, "0 = N/CTS packet disabled", "1 = N/CTS packet enabled", "CTS Request Enable");
    DUMPONEBIT(BIT_2, val, "0: Disable the MCLK input", "1: Enable the MCLK input", "In case of parallel audio I/F, the audio path can be operated without MCLK. Data rate adjustment is then done via TCLK and ACR at the Rx via programmed CTS values. TCLK must be stable enough to ensure audio output quality according to HDMI 1.3 Specification. \n SIMG disclaims any responsibility on audio output quality at the Rx if MCLK is disabled.");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_FREQ_SVAL);
    printk("MCLK input mode: \n 0b000 = MCLK is 128*Fs \n 0b001 = MCLK is 256*Fs \n 0b010 = MCLK is 384*Fs \n 0b011 = MCLK is 512*Fs\n 0b100 = MCLK is 768*Fs\n 0b101 = MCLK is 1024*Fs \n 0b110 = MCLK is 1152*Fs \n 0b111 = MCLK is 192*Fs \n The HDMI Transmitter uses these bits to divide the MCLK input to produce CTS values according to the 128*Fs formula. The MCLK to Fs ratio is for the input Fs, not the down-sampled output Fs (see the ASRC register (0x7A:0x23), on page 64).\n");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_N_SVAL1);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_N_SVAL2);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_N_SVAL3);
    printk("Bits 19:0 N Value for audio clock regeneration method; a 20-bit value. This must be written to the registers to create the correct divisor for audio clock regeneration. Only values greater than 0 are valid. This register must be written after a hardware reset.\n");
    val = FLD_GET(read_reg(HDMI_CORE_AV, HDMI_CORE_AV_N_SVAL3), 3, 0) << BIT_MAX;
    val = (val & read_reg(HDMI_CORE_AV, HDMI_CORE_AV_N_SVAL2)) << BIT_MAX;
    val = val & read_reg(HDMI_CORE_AV, HDMI_CORE_AV_N_SVAL1);
    printk("Bits 19:0 val=%d\n", val);

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_CTS_SVAL1);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_CTS_SVAL2);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_CTS_SVAL3);
    printk("Bits 19:0 CTS Value for audio clock regeneration method; a 20-bit value. For diagnostic use and applied only when the CTS_SEL bit (0x7A:0x01[0]) is set to 1. \n In case of parallel audio I/F, the audio path can be operated without MCLK. Data rate adjustment is then done via TCLK and ACR at the Rx via programmed CTS values. TCLK must be stable enough to ensure audio output quality according to HDMI 1.3 Specification. \n SIMG disclaims any responsibility on audio output quality at the Rx if MCLK is disabled.\n");
    val = FLD_GET(read_reg(HDMI_CORE_AV, HDMI_CORE_AV_CTS_SVAL3), 3, 0) << BIT_MAX;
    val = (val & read_reg(HDMI_CORE_AV, HDMI_CORE_AV_CTS_SVAL2)) << BIT_MAX;
    val = val & read_reg(HDMI_CORE_AV, HDMI_CORE_AV_CTS_SVAL1);
    printk("Bits 19:0 val=%d\n", val);

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_CTS_HVAL1);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_CTS_HVAL2);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_CTS_HVAL3);
    printk("Bits 19:0 CTS Value for audio clock regeneration method; a 20-bit value. This value is measured and stored here by the hardware when MCLK is active and N is valid, after 128Fs/N cycles of MCLK.\n");
    val = FLD_GET(read_reg(HDMI_CORE_AV, HDMI_CORE_AV_CTS_HVAL3), 3, 0) << BIT_MAX;
    val = (val & read_reg(HDMI_CORE_AV, HDMI_CORE_AV_CTS_HVAL2)) << BIT_MAX;
    val = val & read_reg(HDMI_CORE_AV, HDMI_CORE_AV_CTS_HVAL1);
    printk("Bits 19:0 val=%d\n", val);

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_AUD_MODE);
    DUMPREGVAL(val, HDMI_CORE_AV_AUD_MODE);
    DUMPONEBIT(BIT_0, val, "0 = Disable", "1 = Enable", "Audio input stream enable");
    DUMPONEBIT(BIT_1, val, "0 = Disable", "1 = Enable", "S/PDIF input stream enable");
    DUMPONEBIT(BIT_2, val, "0: Parallel audio input disabled", "1: Parallel audio input enabled", "AUD_PAR_EN");
    DUMPONEBIT(BIT_3, val, "0 = Disable", "1 = Enable", "Direct Stream Digital Audio enable");
    DUMPONEBIT(BIT_4, val, "0 = Disable", "1 = Enable", "I2S input channel #0");
    DUMPONEBIT(BIT_5, val, "0 = Disable", "1 = Enable", "I2S input channel #1");
    DUMPONEBIT(BIT_6, val, "0 = Disable", "1 = Enable", "I2S input channel #2");
    DUMPONEBIT(BIT_7, val, "0 = Disable", "1 = Enable", "I2S input channel #3");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_SPDIF_CTRL);
    DUMPREGVAL(val, HDMI_CORE_AV_SPDIF_CTRL);
    DUMPONEBIT(BIT_1, val, "0 = Use input S/PDIF streams detected FS", "1 = Use software FS in I2S_CHST4 register (0x7A:0x21)", "S/PDIF input stream override");
    DUMPONEBIT(BIT_3, val, "0 = Detected change on the S/PDIF input", "1 = No change detected on the S/PDIF input", "No S/PDIF audio");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_HW_SPDIF_FS);
    DUMPREGVAL(val, HDMI_CORE_AV_HW_SPDIF_FS);
    DUMPBITLOG(BIT_3, val, "Bits 3:0 Set to the FS extracted from the S/PDIF input channel status bits 24-27");
    DUMPONEBIT(BIT_4, val, "0 = Maximum sample length is 20 bits", "1 = Maximum sample length is 24 bits", "Maximum sample length (channel status bit 32)");
    DUMPBITLOG(BIT_7, val, "Bits 7:5 Channel status bits 33 to 35 (bit 33=LSB, bit 35=MSB) \n Combines with HW_MAXLEN to indicate sample size: \n Bits  Max 24  Max 20 \n 001  20 bits 16 bits \n 010  22 bits 18 bits \n 100  23 bits 19 bits \n 101  24 bits 20 bits \n 110  21 bits 17 bits");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_SWAP_I2S);
    DUMPREGVAL(val, HDMI_CORE_AV_SWAP_I2S);
    DUMPBITLOG(BIT_3, val, "Bits 3:0 Reserved 每 do not modify. Default 0x9");
    DUMPONEBIT(BIT_4, val, "0 = Do not swap left and right", "1 = Swap left and right", "Swap left-right channels for I2S Channel 0.");
    DUMPONEBIT(BIT_5, val, "0 = Do not swap left and right", "1 = Swap left and right", "Swap left-right channels for I2S Channel 1.");
    DUMPONEBIT(BIT_6, val, "0 = Do not swap left and right", "1 = Swap left and right", "Swap left-right channels for I2S Channel 2.");
    DUMPONEBIT(BIT_7, val, "0 = Do not swap left and right", "1 = Swap left and right", "Swap left-right channels for I2S Channel 3.");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_SPDIF_ERTH);
    printk("Specifies the error threshold level. The frame is marked as invalid if the number of bi-phase mark encoding errors in the audio stream exceeds this threshold level during frame decoding.\n");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_I2S_IN_MAP);
    printk("Bits 7:6 Channel map to FIFO #3 (for HDMI Layout 1), Bits 5:4 to FIFO #2, Bits 3:2 to FIFO #1, Bits 1:0 Channel map to FIFO #0 (for HDMI Layout 0 or 1) \n 0b00 = Map SD0 to FIFO #0 \n 0b01 = Map SD1 to FIFO #0 \n 0b10 = Map SD2 to FIFO #0 \n 0b11 = Map SD3 to FIFO #0 \n");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_I2S_IN_CTRL);
    DUMPREGVAL(val, HDMI_CORE_AV_I2S_IN_CTRL);
    DUMPONEBIT(BIT_0, val, "0 = First bit shift (refer to the Philips Specification)", "1 = No shift", "WS to SD first bit shift");
    DUMPONEBIT(BIT_1, val, "0 = MSB shifted first", "1 = LSB shifted first", "SD direction");
    DUMPONEBIT(BIT_2, val, "0 = Data is left-justified", "1 = Data is right-justified", "SD justify");
    DUMPONEBIT(BIT_3, val, "0 = Left polarity when WS is LOW", "1 = Left polarity when WS is HIGH", "WS polarity");
    DUMPONEBIT(BIT_4, val, "0 = PCM", "1 = Compressed", "V bit value");
    DUMPBITLOG(BIT_5, val, "This bit should be set to 1 for High Bit Rate Audio");
    DUMPONEBIT(BIT_6, val, "0 = Sample edge is falling; SD3-SD0 and WS source should change state on the rising edge of SCK", "1 = Sample clock is rising; SD3-SD0 and WS source should change state on the falling edge of SCK", "SCK sample edge");
    DUMPONEBIT(BIT_7, val, "0 = Input stream is not high bit rate", "1 = Input stream is high bit rate. All of the I2S control bits will apply to the control of the High Bit Rate Audio.", "High Bit Rate Audio On");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_I2S_CHST0);
    printk("Channel Status Byte #0\n");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_I2S_CHST1);
    printk("Channel Status Byte #1: Category Code\n");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_I2S_CHST2);
    printk("Bits 7:4 Channel Status Byte #2: Source Number \n Bits 3:0 Channel Status Byte #2: Source Number\n");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_I2S_CHST4);
    printk("Bits 7:4 Clock Accuracy. \n Bits 3:0 Sampling frequency as set by software, which is inserted into the HDMI audio stream if FS_OVERRIDE (0x7A:0x15[1]) is enabled\n");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_I2S_CHST5);
    DUMPREGVAL(val, HDMI_CORE_AV_I2S_CHST5);
    DUMPONEBIT(BIT_0, val, "0 = 20 bits","1 = 24 bits", "Maximum audio sample word length");
    printk("Bits 7:4 Original Fs. \n Bits 3:0 Audio sample word length: Defined in bits with I2S_MAXLEN: \nI2S_LEN  I2S_MAXLEN=0  I2S_MAXLEN=1 \n 0b001       16            20\n 0b010       18            22\n 0b100       19            23\n 0b101       20            24\n 0b110       17            21\n");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_ASRC);
    DUMPREGVAL(val, HDMI_CORE_AV_ASRC);
    DUMPONEBIT(BIT_0, val, "0 = Disabled", "1 = Enabled", "Audio sample rate conversion");
    DUMPONEBIT(BIT_1, val, "0 = Down-sample 2-to-1 when SRC_EN is set to 1", "1 = Down-sample 4-to-1 when SRC_EN is set to 1", "Sample rate down-conversion ratio");
    printk("Bits 7:4 Mask for the sample present and flat bit of the High Bit Rate Audio header. Each bit masks out one of the subpacket sample present bits.\n 0 = Mask out. 1 = Unmask \n Bits 7:4 must be programmed to 0b0000 when HBRA mode is selected\n");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_I2S_IN_LEN);
    printk("Bits 7:4 The ID of the High Bit Rate Audio packet header.\n");
    printk("Bits 3:0 Number of valid bits in the input I2S stream. Used for the extraction of the I2S data from the input stream. \n 0b1111 每 0b1110 = N/A\n 0b1101 = 21 bit \n 0b1100 = 17 bit \n 0b1011 = 24 bit \n 0b1010 = 20 bit \n 0b1001 = 23 bit \n 0b1000 = 19 bit \n 0b0111 每 0b0110 = N/A \n 0b0101 = 22 bit \n 0b0100 = 18 bit \n 0b0011 = N/A \n 0b0010 = 16 bit \n 0b0001 每 0b0000 = N/A\n");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_AUDO_TXSTAT);
    DUMPREGVAL(val, HDMI_CORE_AV_AUDO_TXSTAT);
    DUMPBITLOG(BIT_0, val, "Enables null packet flooding all the time");
    DUMPBITLOG(BIT_1, val, "Enables null packet flooding only when VSync is high.");
    DUMPONEBIT(BIT_2, val, "0 = No packet with SETAVM=1 has been sent", "1 = A packet with SETAVM=1 has been sent", "General Control Packet mute status");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AUD_PAR_BUSCLK_3);

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_TEST_TXCTRL);
    DUMPREGVAL(val, HDMI_CORE_AV_TEST_TXCTRL);
    DUMPONEBIT(BIT_2, val, "0 - normal operation (default)", "1 - Input pins muxed to TMDS Tx core; to emulate discrete Tx.", "TMDS Core Isolation Enable");
    DUMPONEBIT(BIT_3, val, "0 - normal operation (default).", "1 - bypass DVI encoder logic.", "DVI encoder bypass");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_HDMI_CTRL);
    DUMPREGVAL(val, HDMI_CORE_AV_HDMI_CTRL);
    DUMPONEBIT(BIT_0, val, "0 = Disabled", "1 = Enabled", "HDMI mode");
    DUMPONEBIT(BIT_1, val, "0b00 = Layout 0 (2-channel)", "0b01 = Layout 1 (up to 8 channels)", "Audio packet header layout indicator");
    DUMPBITLOG(BIT_5, val, "Specifies the number of bits per pixel sent to the paketizer: \n 0b100 = 24 bits per pixel (8 bits per pixel; no packing) \n 0b101 = 30 bits per pixel (10 bits per pixel pack to 8 bits) \n 0b110 = 36 bits per pixel (12 bits per pixel pack to 8 bits) \n 0b111 = 48 bits per pixel (16 bits per pixel; no packing) \n Note: The firmware must program 24 bits per pixel (8 bits per pixel; no packing) for initialization.");
    DUMPONEBIT(BIT_6, val, "0 = Do not send deep-color related information in the packet to the HDMI Receiver", "1 = Send deep-color related information in the packet to the HDMI Receiver", "Deep-color packet enable: \n The following data is sent in data byte #1 of the packet: \n 7 = Reserved \n 6 = PP2 \n 5 = PP1 \n 4 = PP0 \n 3 = PP_valid \n 2 = CD2 \n 1 = CD1 \n 0 = CD0 \n The CD bits indicate deep-color mode (defined in the same register bits 5:3). The PP bits indicate the fragment∩s phase related information that comes from the hardware state machine");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_DPD);
    DUMPREGVAL(val, HDMI_CORE_AV_DPD);
    DUMPBITLOG(BIT_0, val, "Power down total: \n a = Power down everything; INT source is RSEN. \n b = Normal operation \n Active high or low depends on used Phy");
    DUMPBITLOG(BIT_1, val, "Power down Internal Oscillator. This disables the I2C port to the internal ROM (disabling loading), halts all interrupt updates, and disables the Master DDC block. \n a = Power down \n b = Normal operation \n Active high or low depends on used Phy");
    DUMPONEBIT(BIT_2, val, "0 = Power down; gate off IDCK signal to disable all IDCK-based logic", "1 = Normal operation", "Power down IDCK input");
    DUMPBITLOG(BIT_3, val, "Selects the TCLK phase: \n a = Default phase; the same as TMDS core \n b = Invert TCLK; change the phase 180 degrees \n Active high or low depends on used Phy");
    DUMPONEBIT(BIT_7, val, "0: Disable", "1: Enable", "Enable bypath of the video path. \n The core_iso_en bit in (reg. 0x13C[1]) must be set and the HDCP cypher must be disabled (reg. 0x72:=x0F[0] == 0)");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_PB_CTRL1);
    DUMPREGVAL(val, HDMI_CORE_AV_PB_CTRL1);
    DUMPONEBIT(BIT_0, val, "0 = Disabled (send once after enable bit is set)", "1 = Enabled (send in every VBLANK period)", "Repeat AVI InfoFrame transmission");
    DUMPONEBIT(BIT_1, val, "0 = Disabled", "1 = Enabled", "Enable AVI InfoFrame transmission:");
    DUMPONEBIT(BIT_2, val, "0 = Disabled (send once after enable bit is set)", "1 = Enabled (send in every VBLANK period)", "Repeat SPD InfoFrame transmission");
    DUMPONEBIT(BIT_3, val, "0 = Disabled", "1 = Enabled", "Enable SPD InfoFrame transmission");
    DUMPONEBIT(BIT_4, val, "0 = Disabled (send once after enable bit is set)", "1 = Enabled (send in every VBLANK period)", "Repeat Audio InfoFrame transmission");
    DUMPONEBIT(BIT_5, val, "0 = Disabled", "1 = Enabled", "Enable Audio InfoFrame transmission");
    DUMPONEBIT(BIT_6, val, "0 = Disabled (send once after enable bit is set)", "1 = Enabled (send in every VBLANK period)", "Repeat MPEG InfoFrame transmission");
    DUMPONEBIT(BIT_7, val, "0 = Disabled", "1 = Enabled", "Enable MPEG InfoFrame transmission");

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_PB_CTRL2);
    DUMPREGVAL(val, HDMI_CORE_AV_PB_CTRL2);
    DUMPONEBIT(BIT_0, val, "0 = Disable (send once after enable bit is set)", "1 = Enable (send in every VBLANK period)", "Repeat Generic Packet transmission");
    DUMPONEBIT(BIT_1, val, "0 = Disabled", "1 = Enabled", "Enable Generic Packet transmission");
    DUMPONEBIT(BIT_2, val, "0 = Disabled (send once after enable bit is set)", "1 = Enabled (send in every VBLANK period)", "Repeat General Control Packet transmission");
    DUMPONEBIT(BIT_3, val, "0 = Disabled", "1 = Enabled", "Enable General Control Packet transmission");
    DUMPONEBIT(BIT_4, val, "0 = Disabled (send once after enable bit is set)", "1 = Enabled (send in every VBLANK period)", "Repeat Generic #2 Packet transmission");
    DUMPONEBIT(BIT_5, val, "0 = Disabled", "1 = Enabled", "Enable Generic #2 Packet transmission");
    DUMPONEBIT(BIT_6, val, "0 = Disabled", "1 = Enabled", "Repeat Gamut Metadata InfoFrame Packet data each frame");
    DUMPONEBIT(BIT_7, val, "0 = Disabled", "1 = Enabled", "Enable Gamut Metadata InfoFrame transmission on HDMI");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AVI_TYPE);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AVI_VERS);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AVI_LEN);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AVI_CHSUM);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AVI_DBYTE);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_SPD_TYPE);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_SPD_VERS);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_SPD_LEN);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_SPD_CHSUM);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_SPD_DBYTE);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AUDIO_TYPE);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AUDIO_VERS);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AUDIO_LEN);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AUDIO_CHSUM);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_AUDIO_DBYTE);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_MPEG_TYPE);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_MPEG_VERS);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_MPEG_LEN);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_MPEG_CHSUM);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_MPEG_DBYTE);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_GEN_DBYTE);
    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_GEN2_DBYTE);

    val = read_reg(HDMI_CORE_AV, HDMI_CORE_AV_CP_BYTE1);
    DUMPREGVAL(val, HDMI_CORE_AV_CP_BYTE1);
    DUMPBITLOG(BIT_0, val, "Set AV Mute flag. \n When the AVMUTE flag is set, the HDMI Transmitter sends a General Control Packet on the TMDS link to inform the Sink that the data may be incorrect. The HDMI Transmitter sends blank-level data for all video packets and 0x00 for all audio packet data. \n When the AVMUTE flag is set, the Sink assumes that no valid data is being received. Optionally, the Sink can apply a mute function to the audio data and/or a blank function to the video data.");
    DUMPBITLOG(BIT_4, val, "Clear AV Mute flag.");

    DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV_CEC_ADDR_ID);
    printk("CEC I2C slave address ID\n");
}
Exemple #25
0
static inline void update_mask_reg(unsigned int reg, u32 mask, u32 or_val)
{
	u32 newval = (read_reg(reg) & mask) | or_val;
	write_reg(reg, newval);
}
Exemple #26
0
void ssd1289_init(void)
{
    lcd_port_init();
    deviceid = read_reg(0x00);

    /* deviceid check */
    if( deviceid != 0x8989 )
    {
        printf("Invalid LCD ID:%08X\r\n",deviceid);
        printf("Please check you hardware and configure.\r\n");
    }
    else
    {
        printf("\r\nLCD Device ID : %04X ",deviceid);
    }

    // power supply setting
    // set R07h at 0021h (GON=1,DTE=0,D[1:0]=01)
    write_reg(0x0007,0x0021);
    // set R00h at 0001h (OSCEN=1)
    write_reg(0x0000,0x0001);
    // set R07h at 0023h (GON=1,DTE=0,D[1:0]=11)
    write_reg(0x0007,0x0023);
    // set R10h at 0000h (Exit sleep mode)
    write_reg(0x0010,0x0000);
    // Wait 30ms
    delay(3000);
    // set R07h at 0033h (GON=1,DTE=1,D[1:0]=11)
    write_reg(0x0007,0x0033);
    // Entry mode setting (R11h)
    // R11H Entry mode
    // vsmode DFM1 DFM0 TRANS OEDef WMode DMode1 DMode0 TY1 TY0 ID1 ID0 AM LG2 LG2 LG0
    //   0     1    1     0     0     0     0      0     0   1   1   1  *   0   0   0
    write_reg(0x0011,0x6070);
    // LCD driver AC setting (R02h)
    write_reg(0x0002,0x0600);
    // power control 1
    // DCT3 DCT2 DCT1 DCT0 BT2 BT1 BT0 0 DC3 DC2 DC1 DC0 AP2 AP1 AP0 0
    // 1     0    1    0    1   0   0  0  1   0   1   0   0   1   0  0
    // DCT[3:0] fosc/4 BT[2:0]  DC{3:0] fosc/4
    write_reg(0x0003,0x0804);//0xA8A4
    write_reg(0x000C,0x0000);//
    write_reg(0x000D,0x0808);// 0x080C --> 0x0808
    // power control 4
    // 0 0 VCOMG VDV4 VDV3 VDV2 VDV1 VDV0 0 0 0 0 0 0 0 0
    // 0 0   1    0    1    0    1    1   0 0 0 0 0 0 0 0
    write_reg(0x000E,0x2900);
    write_reg(0x001E,0x00B8);
    write_reg(0x0001,0x2B3F);//驱动输出控制320*240  0x6B3F
    write_reg(0x0010,0x0000);
    write_reg(0x0005,0x0000);
    write_reg(0x0006,0x0000);
    write_reg(0x0016,0xEF1C);
    write_reg(0x0017,0x0003);
    write_reg(0x0007,0x0233);//0x0233
    write_reg(0x000B,0x0000|(3<<6));
    write_reg(0x000F,0x0000);//扫描开始地址
    write_reg(0x0041,0x0000);
    write_reg(0x0042,0x0000);
    write_reg(0x0048,0x0000);
    write_reg(0x0049,0x013F);
    write_reg(0x004A,0x0000);
    write_reg(0x004B,0x0000);
    write_reg(0x0044,0xEF00);
    write_reg(0x0045,0x0000);
    write_reg(0x0046,0x013F);
    write_reg(0x0030,0x0707);
    write_reg(0x0031,0x0204);
    write_reg(0x0032,0x0204);
    write_reg(0x0033,0x0502);
    write_reg(0x0034,0x0507);
    write_reg(0x0035,0x0204);
    write_reg(0x0036,0x0204);
    write_reg(0x0037,0x0502);
    write_reg(0x003A,0x0302);
    write_reg(0x003B,0x0302);
    write_reg(0x0023,0x0000);
    write_reg(0x0024,0x0000);
    write_reg(0x0025,0x8000);   // 65hz
    write_reg(0x004f,0);        // 行首址0
    write_reg(0x004e,0);        // 列首址0

    //数据总线测试,用于测试硬件连接是否正常.
    lcd_data_bus_test();
    //GRAM测试,此测试可以测试LCD控制器内部GRAM.测试通过保证硬件正常
//    lcd_gram_test();

    //清屏
    lcd_clear( Blue );
}
static int find_mtp(struct msm_fb_data_type *mfd, char * mtp)
{
#if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT)
	char first_mtp[MTP_DATA_SIZE_S6E63M0];
	char second_mtp[MTP_DATA_SIZE_S6E63M0];
	char third_mtp[MTP_DATA_SIZE_S6E63M0];
	int mtp_size = MTP_DATA_SIZE_S6E63M0;
#elif defined(CONFIG_FB_MSM_MIPI_MAGNA_OLED_VIDEO_WVGA_PT)
	char first_mtp[MTP_DATA_SIZE_EA8868];
	char second_mtp[MTP_DATA_SIZE_EA8868];
	char third_mtp[MTP_DATA_SIZE_EA8868];
	int mtp_size = MTP_DATA_SIZE_EA8868;
#else
	/*
	*	s6e8aa0x01 & s6e39a0x02 has same MTP length.
	*/
	char first_mtp[MTP_DATA_SIZE];
	char second_mtp[MTP_DATA_SIZE];
	char third_mtp[MTP_DATA_SIZE];
	int mtp_size = MTP_DATA_SIZE;
#endif
	int correct_mtp;

	pr_info("first time mpt read\n");
	read_reg(MTP_REGISTER, mtp_size, first_mtp, FALSE, mfd);

	pr_info("second time mpt read\n");
	read_reg(MTP_REGISTER, mtp_size, second_mtp, FALSE, mfd);

	if (memcmp(first_mtp, second_mtp, mtp_size) != 0) {
		pr_info("third time mpt read\n");
		read_reg(MTP_REGISTER, mtp_size, third_mtp, FALSE, mfd);

		if (memcmp(first_mtp, third_mtp, mtp_size) == 0) {
			pr_info("MTP data is used from first read mtp");
			memcpy(mtp, first_mtp, mtp_size);
			correct_mtp = 1;
		} else if (memcmp(second_mtp, third_mtp, mtp_size) == 0) {
			pr_info("MTP data is used from second read mtp");
			memcpy(mtp, second_mtp, mtp_size);
			correct_mtp = 2;
		} else {
			pr_info("MTP data is used 0 read mtp");
			memset(mtp, 0, mtp_size);
			correct_mtp = 0;
		}
	} else {
		pr_info("MTP data is used from first read mtp");
		memcpy(mtp, first_mtp, mtp_size);
		correct_mtp = 1;
	}

#if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT)
	/*
	*	checking V1 MTP value. V0 value must be 0.
	*/
	if ((mtp[0] != 0) || (mtp[7] != 0) || (mtp[14] != 0)) {
		memset(mtp, 0, mtp_size);
		correct_mtp = 0;
	}
#endif
	return correct_mtp;
}
Exemple #28
0
static int omap2_onenand_wait(struct mtd_info *mtd, int state)
{
	struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
	unsigned int intr = 0;
	unsigned int ctrl;
	unsigned long timeout;
	u32 syscfg;

	if (state == FL_RESETING) {
		int i;

		for (i = 0; i < 20; i++) {
			udelay(1);
			intr = read_reg(c, ONENAND_REG_INTERRUPT);
			if (intr & ONENAND_INT_MASTER)
				break;
		}
		ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
		if (ctrl & ONENAND_CTRL_ERROR) {
			wait_err("controller error", state, ctrl, intr);
			return -EIO;
		}
		if (!(intr & ONENAND_INT_RESET)) {
			wait_err("timeout", state, ctrl, intr);
			return -EIO;
		}
		return 0;
	}

	if (state != FL_READING) {
		int result;

		/* Turn interrupts on */
		syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
		if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) {
			syscfg |= ONENAND_SYS_CFG1_IOBE;
			write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
			if (cpu_is_omap34xx())
				/* Add a delay to let GPIO settle */
				syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
		}

		INIT_COMPLETION(c->irq_done);
		if (c->gpio_irq) {
			result = gpio_get_value(c->gpio_irq);
			if (result == -1) {
				ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
				intr = read_reg(c, ONENAND_REG_INTERRUPT);
				wait_err("gpio error", state, ctrl, intr);
				return -EIO;
			}
		} else
			result = 0;
		if (result == 0) {
			int retry_cnt = 0;
retry:
			result = wait_for_completion_timeout(&c->irq_done,
						    msecs_to_jiffies(20));
			if (result == 0) {
				/* Timeout after 20ms */
				ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
				if (ctrl & ONENAND_CTRL_ONGO) {
					/*
					 * The operation seems to be still going
					 * so give it some more time.
					 */
					retry_cnt += 1;
					if (retry_cnt < 3)
						goto retry;
					intr = read_reg(c,
							ONENAND_REG_INTERRUPT);
					wait_err("timeout", state, ctrl, intr);
					return -EIO;
				}
				intr = read_reg(c, ONENAND_REG_INTERRUPT);
				if ((intr & ONENAND_INT_MASTER) == 0)
					wait_warn("timeout", state, ctrl, intr);
			}
		}
	} else {
		int retry_cnt = 0;

		/* Turn interrupts off */
		syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
		syscfg &= ~ONENAND_SYS_CFG1_IOBE;
		write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);

		timeout = jiffies + msecs_to_jiffies(20);
		while (1) {
			if (time_before(jiffies, timeout)) {
				intr = read_reg(c, ONENAND_REG_INTERRUPT);
				if (intr & ONENAND_INT_MASTER)
					break;
			} else {
				/* Timeout after 20ms */
				ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
				if (ctrl & ONENAND_CTRL_ONGO) {
					/*
					 * The operation seems to be still going
					 * so give it some more time.
					 */
					retry_cnt += 1;
					if (retry_cnt < 3) {
						timeout = jiffies +
							  msecs_to_jiffies(20);
						continue;
					}
				}
				break;
			}
		}
	}

	intr = read_reg(c, ONENAND_REG_INTERRUPT);
	ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);

	if (intr & ONENAND_INT_READ) {
		int ecc = read_reg(c, ONENAND_REG_ECC_STATUS);

		if (ecc) {
			unsigned int addr1, addr8;

			addr1 = read_reg(c, ONENAND_REG_START_ADDRESS1);
			addr8 = read_reg(c, ONENAND_REG_START_ADDRESS8);
			if (ecc & ONENAND_ECC_2BIT_ALL) {
				printk(KERN_ERR "onenand_wait: ECC error = "
				       "0x%04x, addr1 %#x, addr8 %#x\n",
				       ecc, addr1, addr8);
				mtd->ecc_stats.failed++;
				return -EBADMSG;
			} else if (ecc & ONENAND_ECC_1BIT_ALL) {
				printk(KERN_NOTICE "onenand_wait: correctable "
				       "ECC error = 0x%04x, addr1 %#x, "
				       "addr8 %#x\n", ecc, addr1, addr8);
				mtd->ecc_stats.corrected++;
			}
		}
	} else if (state == FL_READING) {
		wait_err("timeout", state, ctrl, intr);
		return -EIO;
	}

	if (ctrl & ONENAND_CTRL_ERROR) {
		wait_err("controller error", state, ctrl, intr);
		if (ctrl & ONENAND_CTRL_LOCK)
			printk(KERN_ERR "onenand_wait: "
					"Device is write protected!!!\n");
		return -EIO;
	}

	if (ctrl & 0xFE9F)
		wait_warn("unexpected controller status", state, ctrl, intr);

	return 0;
}
Exemple #29
0
/*
 * Interrupt handler
 */
static irqreturn_t snd_ps3_interrupt(int irq, void *dev_id)
{

	uint32_t port_intr;
	int underflow_occured = 0;
	struct snd_ps3_card_info *card = dev_id;

	if (!card->running) {
		update_reg(PS3_AUDIO_AX_IS, 0);
		update_reg(PS3_AUDIO_INTR_0, 0);
		return IRQ_HANDLED;
	}

	port_intr = read_reg(PS3_AUDIO_AX_IS);
	/*
	 *serial buffer empty detected (every 4 times),
	 *program next dma and kick it
	 */
	if (port_intr & PS3_AUDIO_AX_IE_ASOBEIE(0)) {
		write_reg(PS3_AUDIO_AX_IS, PS3_AUDIO_AX_IE_ASOBEIE(0));
		if (port_intr & PS3_AUDIO_AX_IE_ASOBUIE(0)) {
			write_reg(PS3_AUDIO_AX_IS, port_intr);
			underflow_occured = 1;
		}
		if (card->silent) {
			/* we are still in silent time */
			snd_ps3_program_dma(card,
				(underflow_occured) ?
				SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL :
				SND_PS3_DMA_FILLTYPE_SILENT_RUNNING);
			snd_ps3_kick_dma(card);
			card->silent--;
		} else {
			snd_ps3_program_dma(card,
				(underflow_occured) ?
				SND_PS3_DMA_FILLTYPE_FIRSTFILL :
				SND_PS3_DMA_FILLTYPE_RUNNING);
			snd_ps3_kick_dma(card);
			snd_pcm_period_elapsed(card->substream);
		}
	} else if (port_intr & PS3_AUDIO_AX_IE_ASOBUIE(0)) {
		write_reg(PS3_AUDIO_AX_IS, PS3_AUDIO_AX_IE_ASOBUIE(0));
		/*
		 * serial out underflow, but buffer empty not detected.
		 * in this case, fill fifo with 0 to recover.  After
		 * filling dummy data, serial automatically start to
		 * consume them and then will generate normal buffer
		 * empty interrupts.
		 * If both buffer underflow and buffer empty are occured,
		 * it is better to do nomal data transfer than empty one
		 */
		snd_ps3_program_dma(card,
				    SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL);
		snd_ps3_kick_dma(card);
		snd_ps3_program_dma(card,
				    SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL);
		snd_ps3_kick_dma(card);
	}
	/* clear interrupt cause */
	return IRQ_HANDLED;
};
/*
 * SMBUS-type transfer entrypoint
 */
static s32
keywest_smbus_xfer(	struct i2c_adapter*	adap,
			u16			addr,
			unsigned short		flags,
			char			read_write,
			u8			command,
			int			size,
			union i2c_smbus_data*	data)
{
	struct keywest_chan* chan = i2c_get_adapdata(adap);
	struct keywest_iface* iface = chan->iface;
	int len;
	u8* buffer;
	u16 cur_word;
	int rc = 0;

	if (iface->state == state_dead)
		return -ENXIO;
		
	/* Prepare datas & select mode */
	iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK;
	switch (size) {
        case I2C_SMBUS_QUICK:
	    	len = 0;
	    	buffer = NULL;
	    	iface->cur_mode |= KW_I2C_MODE_STANDARD;
	    	break;
        case I2C_SMBUS_BYTE:
	    	len = 1;
	    	buffer = &data->byte;
	    	iface->cur_mode |= KW_I2C_MODE_STANDARD;
	    	break;
        case I2C_SMBUS_BYTE_DATA:
	    	len = 1;
	    	buffer = &data->byte;
	    	iface->cur_mode |= KW_I2C_MODE_STANDARDSUB;
	    	break;
        case I2C_SMBUS_WORD_DATA:
	    	len = 2;
	    	cur_word = cpu_to_le16(data->word);
	    	buffer = (u8 *)&cur_word;
	    	iface->cur_mode |= KW_I2C_MODE_STANDARDSUB;
		break;
        case I2C_SMBUS_BLOCK_DATA:
	    	len = data->block[0];
	    	buffer = &data->block[1];
	    	iface->cur_mode |= KW_I2C_MODE_STANDARDSUB;
		break;
        default:
	    	return -1;
	}

	/* Turn a standardsub read into a combined mode access */
 	if (read_write == I2C_SMBUS_READ
 	    && (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB) {
 		iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK;
 		iface->cur_mode |= KW_I2C_MODE_COMBINED;
 	}

	/* Original driver had this limitation */
	if (len > 32)
		len = 32;

	if (pmac_low_i2c_lock(iface->node))
		return -ENXIO;

	pr_debug("chan: %d, addr: 0x%x, transfer len: %d, read: %d\n",
		chan->chan_no, addr, len, read_write == I2C_SMBUS_READ);

	iface->data = buffer;
	iface->datalen = len;
	iface->state = state_addr;
	iface->result = 0;
	iface->read_write = read_write;
	
	/* Setup channel & clear pending irqs */
	write_reg(reg_isr, read_reg(reg_isr));
	write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4));
	write_reg(reg_status, 0);

	/* Set up address and r/w bit */
	write_reg(reg_addr,
		(addr << 1) | ((read_write == I2C_SMBUS_READ) ? 0x01 : 0x00));

	/* Set up the sub address */
	if ((iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB
	    || (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED)
		write_reg(reg_subaddr, command);

#ifndef POLLED_MODE
	/* Arm timeout */
	iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
	add_timer(&iface->timeout_timer);
#endif

	/* Start sending address & enable interrupt*/
	write_reg(reg_control, KW_I2C_CTL_XADDR);
	write_reg(reg_ier, KW_I2C_IRQ_MASK);

#ifdef POLLED_MODE
	pr_debug("using polled mode...\n");
	/* State machine, to turn into an interrupt handler */
	while(iface->state != state_idle) {
		unsigned long flags;

		u8 isr = wait_interrupt(iface);
		spin_lock_irqsave(&iface->lock, flags);
		handle_interrupt(iface, isr);
		spin_unlock_irqrestore(&iface->lock, flags);
	}
#else /* POLLED_MODE */
	pr_debug("using interrupt mode...\n");
	wait_for_completion(&iface->complete);	
#endif /* POLLED_MODE */	

	rc = iface->result;	
	pr_debug("transfer done, result: %d\n", rc);

	if (rc == 0 && size == I2C_SMBUS_WORD_DATA && read_write == I2C_SMBUS_READ)
	    	data->word = le16_to_cpu(cur_word);
	
	/* Release sem */
	pmac_low_i2c_unlock(iface->node);
	
	return rc;
}