Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ or OP-TEE leaves every interrupt secure and Linux hangs after the timer.
shell. Video input: `aw-vinc` paints test frames into buffers behind
`aw-iommu` (the media masters use IOMMU addresses); `aw-ve` answers the
VE ID CedarC's compiled-in table and its LBC check accept (0xE0/0xE4 =
0x21110/0x21210); the sensor is `hisi-gc2053` on TWI1; `aw-pio` reads
0x21110/0x21210); the sensor is the catalogue's `gc2053` on TWI1; `aw-pio` reads
inputs high (stored zeros were the YI reset button held down).
`qemu-boot/yi-v831-prepare.sh` makes a YI image that runs as if paired.
`aw-ve` encodes H.264: CedarC puts the headers through the bitstream
Expand Down Expand Up @@ -596,12 +596,20 @@ in this order:
`chip_variant` (and `v1_chip_id_88`/`_8c` for the V1 quartet) or firmware
prints `Wrong chip-id`/`hiunknown` and `load_hisilicon` bails before loading
any vendor module. CI greps for exactly this.
- **Sensors** are I2C/SSI slave models in `qemu/hw/i2c/` and `qemu/hw/ssi/`,
selected by name in a `strcmp` chain in `hisilicon_common_init()`
(`imx335`, `imx307`, `f37`, `gc2053`, `sc2315e`, … , or `none`).
The Xiongmai machines take a QOM type name instead (`sensor=hisi-imx335`,
`sensor=none`) plus `sensor-addr=`; `xm-sensor` is a generic register-file
sensor whose ID comes from `-global xm-sensor.regs=` (`docs/xiongmai.md`).
- **Sensors** are I2C slave models in `qemu/hw/i2c/`, shared by every family
and built for every target. `sensor=` names one from the catalogue in
`hw/i2c/image-sensor.c` (name, model, 7-bit address, chip ID): add a part
there, not in a machine, and every machine takes it through
`image_sensor_create()`. A part new to the catalogue usually needs only a
line: SmartSens and GalaxyCore parts share a model. Take its ID from the
vendor driver. An ISP reads a sensor through the `image-sensor` interface
(`image_sensor_exposure()`); a model implements it from its registers. The
plain Sony models, `hisi-mis2006` and `hisi-sp2305` do not yet: on an ISP
that needs a picture from the sensor they are found but draw nothing.
The Xiongmai machines also take a QOM type name (`sensor=hisi-imx335`) plus
`sensor-addr=`; `xm-sensor` is a generic register-file sensor whose ID comes
from `-global xm-sensor.regs=` (`docs/xiongmai.md`). The SSI `imx122` stays
in `hisilicon_common_init()`.

## Adding a SoC or a device

Expand Down
2 changes: 1 addition & 1 deletion docs/allwinner-v83x.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ starts, stays up, and with a configured camera opens its H.264 encoder.
on LBC input. 0x1707 (an older guess) passes the VE layer but the
encoder refuses it. The ID is chosen from the firmware's table, not
read from silicon.
- **Sensor.** The repo's GC2053 (`hisi-gc2053`, ID 0x2053 at 0xF0/0xF1)
- **Sensor.** The catalogue's GC2053 (`galaxycore-sensor`, ID 0x2053 at 0xF0/0xF1)
sits at 0x37 on TWI1. The VIN driver registers its video nodes and the
ISP library finds its `gc2053_mipi_1936_1096_20` tuning.
- **Frames.** `aw-vinc` paints the OpenIPC logo (still, white on navy)
Expand Down
21 changes: 21 additions & 0 deletions docs/sigmastar.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,27 @@ timers count the 12 MHz crystal, timer 0 the 432 MHz MPLL divided by
Reading a counter's low half latches its high half: U-Boot takes any step
back for a 32-bit wrap.

## Boards

The `msc313e` machine takes other infinity3 boards through its options. The
firmware expects the board's own sensor and RAM: with the wrong sensor an
app gives up (Anjoy's reboots, Raysharp's dies under its watchdog), and with
too little RAM the kernel's CMA pool wraps onto low memory and corrupts it.
A board's real values are in its dump: the sensor from `Sensor_id_table` in
the `libdrv_ms_cus_*.so` it ships, the RAM from the kernel's `Memory:` line.

| Board | Options | Result |
|---|---|---|
| Jabsco C3001, C301-M15 | `sensor=jxf22` (the default) | login, app runs |
| Anjoy YM200J, YM200J2 | `sensor=imx307` | YM200J: H.264 over RTSP; AE converges |
| Anjoy MC300E10 (its "SC32xx" name notwithstanding) | `sensor=sc2315e` | no reboot, AE converges |
| Raysharp MSC316D (RS-CH228M2NN) | `sensor=sc2310,rtc=ds1338 -m 128M` | video pipeline runs, AE converges |
| MSC316DC | `sensor=imx323 -m 128M` | video pipeline runs; picture saturates, AE does not settle |

`rtc=ds1338` puts a DS1307-family RTC at 0x68 (0xD0 in 8-bit) on the first
I2C bus, where the Raysharp app reads its time. The Anjoy `CRY` driver
(`/dev/cry`) reads "failed" on every board here and the firmware runs on.

## Devices

- **SPI NOR** (`sstar-fsp`). One generic 3-byte-address NOR behind the four
Expand Down
4 changes: 2 additions & 2 deletions qemu/hw/arm/allwinner-v83x.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "hw/char/serial-mm.h"
#include "hw/i2c/allwinner-i2c.h"
#include "hw/i2c/i2c.h"
#include "hw/i2c/image-sensor.h"
#include "hw/intc/arm_gic.h"
#include "hw/net/allwinner-sun8i-emac.h"
#include "hw/intc/arm_gic_common.h"
Expand Down Expand Up @@ -457,8 +458,7 @@ static void aw_v83x_common_init(MachineState *machine, const AwSoCConfig *c)
* The camera sensor, a GC2053 at 0x37 on TWI1 (the vendor
* vind DT and gc2053_mipi.c): ID 0x2053 at 0xF0/0xF1.
*/
i2c_slave_create_simple(I2C_BUS(qdev_get_child_bus(twi, "i2c")),
"hisi-gc2053", 0x37);
image_sensor_create(I2C_BUS(qdev_get_child_bus(twi, "i2c")), "gc2053");
}
sysbus_create_simple("aw-twi", base + 0x200,
qdev_get_gpio_in(orgate, 1));
Expand Down
50 changes: 3 additions & 47 deletions qemu/hw/arm/fullhan.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include "hw/boards.h"
#include "hw/cpu/a15mpcore.h"
#include "hw/i2c/i2c.h"
#include "hw/i2c/image-sensor.h"
#include "hw/irq.h"
#include "hw/loader.h"
#include "hw/misc/unimp.h"
Expand Down Expand Up @@ -434,51 +435,6 @@ static void fh_machine_set_sensor(Object *obj, const char *value,
* turn: the FH885xV200 ones GC2063 (0x37), GC4653 (0x29), MIS2006 (0x30);
* the V100 / FH8626 ones GC2053, GC2093, GC1054, JX-F37, MIS2006.
*/
static const struct {
const char *name;
const char *type; /* NULL: galaxycore-sensor */
uint8_t addr;
bool reg16;
uint16_t id_reg, id;
} fh_sensors[] = {
{ "gc4653", NULL, 0x29, true, 0x03F0, 0x4653 },
{ "gc2053", NULL, 0x37, false, 0xF0, 0x2053 },
{ "gc2063", NULL, 0x37, false, 0xF0, 0x2063 },
{ "gc2093", NULL, 0x37, true, 0x03F0, 0x2093 },
{ "gc1054", NULL, 0x21, false, 0xF0, 0x1054 },
{ "mis2006", "hisi-mis2006", 0x30 },
{ "f37", "hisi-f37", 0x40 },
};

static void fh_create_sensor(const char *name, I2CBus *bus)
{
DeviceState *dev;
int n;

if (!name || !strcmp(name, "none")) {
return;
}
for (n = 0; n < ARRAY_SIZE(fh_sensors); n++) {
if (!strcmp(name, fh_sensors[n].name)) {
break;
}
}
if (n == ARRAY_SIZE(fh_sensors)) {
error_report("fullhan: unknown sensor '%s' (none, gc4653, gc2053, "
"gc2063, gc2093, gc1054, mis2006, f37)", name);
exit(1);
}
if (fh_sensors[n].type) {
i2c_slave_create_simple(bus, fh_sensors[n].type, fh_sensors[n].addr);
return;
}
dev = DEVICE(i2c_slave_new("galaxycore-sensor", fh_sensors[n].addr));
qdev_prop_set_bit(dev, "reg16", fh_sensors[n].reg16);
qdev_prop_set_uint16(dev, "id-reg", fh_sensors[n].id_reg);
qdev_prop_set_uint16(dev, "id", fh_sensors[n].id);
i2c_slave_realize_and_unref(I2C_SLAVE(dev), bus, &error_fatal);
}

/* Interrupt n of the SoC's numbering: DW ICTL input n, or GIC SPI n. */
static qemu_irq fh_irq(FhMachineState *fms, int n)
{
Expand Down Expand Up @@ -826,8 +782,8 @@ static void fullhan_common_init(MachineState *machine, const FhSoCConfig *c)
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
fh_irq(fms, c->i2c_irq[n]));
if (n == 0) {
fh_create_sensor(fms->sensor ? fms->sensor : c->sensor,
(I2CBus *)qdev_get_child_bus(dev, "i2c"));
image_sensor_create(I2C_BUS(qdev_get_child_bus(dev, "i2c")),
fms->sensor ? fms->sensor : c->sensor);
}
}

Expand Down
29 changes: 4 additions & 25 deletions qemu/hw/arm/goke.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "hw/boards.h"
#include "hw/char/serial-mm.h"
#include "hw/i2c/i2c.h"
#include "hw/i2c/image-sensor.h"
#include "hw/or-irq.h"
#include "hw/irq.h"
#include "hw/loader.h"
Expand Down Expand Up @@ -284,16 +285,6 @@ static void gk_machine_set_sensor(Object *obj, const char *value,

/* Sensors a GK7102 board may carry that have a model: I2C type, 7-bit
* address on IDC 0. */
static const struct {
const char *name;
const char *type;
uint8_t addr;
} gk_sensors[] = {
{ "jxh42", "hisi-jxh42", 0x30 },
{ "jxh62", "hisi-jxh62", 0x30 },
{ "f37", "hisi-f37", 0x40 },
};

/*
* The mask ROM's boot header, in CPU words (the flash holds each word
* byte-swapped, see gk-sflash.c):
Expand Down Expand Up @@ -745,21 +736,9 @@ static void goke_common_init(MachineState *machine, const GkSoCConfig *c)
gk_map_model(c, dev, c->idc_bases[n], "idc", 0x1000);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
gk_irq(vic, c, c->idc_irqs[n]));
if (n == 0 && gms->sensor && strcmp(gms->sensor, "none")) {
int i;

for (i = 0; i < ARRAY_SIZE(gk_sensors); i++) {
if (!strcmp(gms->sensor, gk_sensors[i].name)) {
break;
}
}
if (i == ARRAY_SIZE(gk_sensors)) {
error_report("goke: unknown sensor '%s' (none, jxh42, "
"jxh62, f37)", gms->sensor);
exit(1);
}
i2c_slave_create_simple(I2C_BUS(qdev_get_child_bus(dev, "i2c")),
gk_sensors[i].type, gk_sensors[i].addr);
if (n == 0) {
image_sensor_create(I2C_BUS(qdev_get_child_bus(dev, "i2c")),
gms->sensor);
}
}

Expand Down
38 changes: 2 additions & 36 deletions qemu/hw/arm/grainmedia.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
#include "hw/boards.h"
#include "hw/char/serial-mm.h"
#include "hw/i2c/i2c.h"
#include "hw/i2c/image-sensor.h"
#include "hw/irq.h"
#include "hw/loader.h"
#include "hw/misc/unimp.h"
Expand Down Expand Up @@ -215,16 +216,6 @@ static const struct {
* (fisp_<sensor>.ko) probe them: 16-bit register addresses, the ID in
* two registers.
*/
static const struct {
const char *name;
uint8_t addr;
uint16_t id_reg;
uint16_t id;
} gm_sensors[] = {
{ "ov2715", 0x36, 0x300A, 0x2715 }, /* the Longse cameras' */
{ "ov9715", 0x30, 0x300A, 0x9711 },
};

struct GmMachineState {
MachineState parent_obj;
char *flash_file;
Expand Down Expand Up @@ -275,31 +266,6 @@ static void gm_machine_set_sensor(Object *obj, const char *value,
s->sensor = g_strdup(value);
}

static void gm_create_sensor(const char *name, I2CBus *bus)
{
DeviceState *dev;
int i;

if (!name || !strcmp(name, "none")) {
return;
}
for (i = 0; i < ARRAY_SIZE(gm_sensors); i++) {
if (!strcmp(name, gm_sensors[i].name)) {
break;
}
}
if (i == ARRAY_SIZE(gm_sensors)) {
error_report("grainmedia: unknown sensor '%s'", name);
exit(1);
}
dev = qdev_new("galaxycore-sensor");
qdev_prop_set_bit(dev, "reg16", true);
qdev_prop_set_uint16(dev, "id-reg", gm_sensors[i].id_reg);
qdev_prop_set_uint16(dev, "id", gm_sensors[i].id);
qdev_prop_set_uint8(dev, "address", gm_sensors[i].addr);
qdev_realize_and_unref(dev, BUS(bus), &error_fatal);
}

static qemu_irq gm_irq(GmMachineState *gms, int n)
{
return qdev_get_gpio_in(gms->intc, n);
Expand Down Expand Up @@ -659,7 +625,7 @@ static void grainmedia_common_init(MachineState *machine,

dev = sysbus_create_simple("gm-i2c", GM_I2C_BASE,
gm_irq(gms, GM_IRQ_I2C));
gm_create_sensor(gms->sensor, (I2CBus *)qdev_get_child_bus(dev, "i2c"));
image_sensor_create(I2C_BUS(qdev_get_child_bus(dev, "i2c")), gms->sensor);

binfo.ram_size = machine->ram_size;
binfo.loader_start = 0;
Expand Down
87 changes: 3 additions & 84 deletions qemu/hw/arm/hisilicon.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "system/block-backend.h"
#include "net/net.h"
#include "hw/i2c/i2c.h"
#include "hw/i2c/image-sensor.h"
#include "hw/clock.h"
#include "hw/qdev-clock.h"
#include "target/arm/cpu-qom.h"
Expand Down Expand Up @@ -6056,90 +6057,8 @@ static void hisilicon_common_init(MachineState *machine,
DeviceState *sensor = qdev_new("hisi-imx122");
qdev_realize_and_unref(sensor, ssi_bus, &error_fatal);
} else if (sensor_name && c->num_i2c > 0 && i2c_devs[0]) {
BusState *i2c_bus = qdev_get_child_bus(i2c_devs[0], "i2c");
DeviceState *sensor = NULL;
uint8_t i2c_addr = 0;

if (!strcmp(sensor_name, "imx335")) {
sensor = qdev_new("hisi-imx335");
i2c_addr = 0x1A;
} else if (!strcmp(sensor_name, "imx307")) {
sensor = qdev_new("hisi-imx307");
i2c_addr = 0x1A;
} else if (!strcmp(sensor_name, "imx291")) {
sensor = qdev_new("hisi-imx291");
i2c_addr = 0x1A;
} else if (!strcmp(sensor_name, "imx415")) {
sensor = qdev_new("hisi-imx415");
i2c_addr = 0x1A;
} else if (!strcmp(sensor_name, "imx385")) {
sensor = qdev_new("hisi-imx385");
i2c_addr = 0x1A;
} else if (!strcmp(sensor_name, "f37")) {
sensor = qdev_new("hisi-f37");
i2c_addr = 0x40;
} else if (!strcmp(sensor_name, "gc2053")) {
sensor = qdev_new("hisi-gc2053");
i2c_addr = 0x37;
} else if (!strcmp(sensor_name, "sp2305")) {
sensor = qdev_new("hisi-sp2305");
i2c_addr = 0x3C;
} else if (!strcmp(sensor_name, "mis2006")) {
sensor = qdev_new("hisi-mis2006");
i2c_addr = 0x30;
} else if (!strcmp(sensor_name, "nvp6124b")) {
sensor = qdev_new("hisi-nvp6124b");
i2c_addr = 0x60; /* 7-bit; vendor uses 0x60..0x66 */
} else if (!strcmp(sensor_name, "sc2315e")) {
sensor = qdev_new("hisi-smartsens");
qdev_prop_set_uint8(sensor, "id_high", 0x22);
qdev_prop_set_uint8(sensor, "id_low", 0x38);
i2c_addr = 0x30;
} else if (!strcmp(sensor_name, "sc2315")) {
sensor = qdev_new("hisi-smartsens");
qdev_prop_set_uint8(sensor, "id_high", 0x23);
qdev_prop_set_uint8(sensor, "id_low", 0x11);
i2c_addr = 0x30;
} else if (!strcmp(sensor_name, "sc2235p")) {
sensor = qdev_new("hisi-smartsens");
qdev_prop_set_uint8(sensor, "id_high", 0x22);
qdev_prop_set_uint8(sensor, "id_low", 0x32);
qdev_prop_set_uint8(sensor, "disc", 0x01);
i2c_addr = 0x30;
} else if (!strcmp(sensor_name, "sc2235e")) {
sensor = qdev_new("hisi-smartsens");
qdev_prop_set_uint8(sensor, "id_high", 0x22);
qdev_prop_set_uint8(sensor, "id_low", 0x32);
qdev_prop_set_uint8(sensor, "disc", 0x20);
i2c_addr = 0x30;
} else if (!strcmp(sensor_name, "sc2335")) {
sensor = qdev_new("hisi-smartsens");
qdev_prop_set_uint8(sensor, "id_high", 0xCB);
qdev_prop_set_uint8(sensor, "id_low", 0x14);
i2c_addr = 0x30;
} else if (!strcmp(sensor_name, "sc2239")) {
sensor = qdev_new("hisi-smartsens");
qdev_prop_set_uint8(sensor, "id_high", 0xCB);
qdev_prop_set_uint8(sensor, "id_low", 0x10);
i2c_addr = 0x30;
} else if (!strcmp(sensor_name, "sc307h")) {
sensor = qdev_new("hisi-smartsens");
qdev_prop_set_uint8(sensor, "id_high", 0xCB);
qdev_prop_set_uint8(sensor, "id_low", 0x1C);
i2c_addr = 0x30;
} else {
error_report("Unknown sensor '%s' (supported: imx291, "
"imx307, imx335, imx385, imx415, f37, "
"gc2053, sp2305, mis2006, nvp6124b, "
"sc2235p, sc2235e, sc2315, sc2315e, sc2335, "
"sc2239, sc307h, imx122, imx222; or 'none' "
"to disable default)",
sensor_name);
exit(1);
}

qdev_prop_set_uint8(sensor, "address", i2c_addr);
qdev_realize_and_unref(sensor, i2c_bus, &error_fatal);
image_sensor_create(I2C_BUS(qdev_get_child_bus(i2c_devs[0], "i2c")),
sensor_name);
} else if (sensor_name) {
error_report("sensor '%s' requested but this SoC has no I2C "
"or matching SPI controller", sensor_name);
Expand Down
Loading
Loading