Skip to content
Open
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
1 change: 1 addition & 0 deletions drivers/media/platform/phytium/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ config VIDEO_PHYTIUM_JPEG
tristate "Phytium JPEG Encoder Engine driver"
depends on V4L_PLATFORM_DRIVERS
depends on VIDEO_DEV
depends on ARCH_PHYTIUM
select VIDEOBUF2_DMA_CONTIG
help
Support for the Phytium JPEG Encoder Engine embedded
Expand Down
61 changes: 42 additions & 19 deletions drivers/media/platform/phytium/phytium_jpeg_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,6 @@ static void phytium_jpeg_off(struct phytium_jpeg_dev *jpeg_dev)
}

clear_bit(VIDEO_CLOCKS_ON, &jpeg_dev->status);
/* wait 50 ms */
mdelay(50);
/* C08 bit7 1:busy */
}

static inline void phytium_jpeg_enable_source_detecting(struct phytium_jpeg_dev *jpeg_dev)
Expand All @@ -210,22 +207,47 @@ static void phytium_jpeg_get_resolution(struct phytium_jpeg_dev *jpeg_dev)
u32 width;
u32 height;
struct v4l2_bt_timings *detected_timings = &jpeg_dev->detected_timings;
u32 input_signal;

/* Before get a new resolution, maybe need to wait 10 us */
detected_timings->width = MIN_WIDTH;
detected_timings->height = MIN_HEIGHT;
jpeg_dev->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;


phytium_jpeg_enable_source_detecting(jpeg_dev);
source_info = phytium_jpeg_read(jpeg_dev, SRC_VGA_INFO_REG);
width = (source_info & SRC_HOR_PIXELS) >> SRC_WIDTH_SHIFT;
height = (source_info & SRC_VER_PIXELS) >> SRC_HEIGHT_SHIFT;

input_signal = phytium_jpeg_read(jpeg_dev, BUF_LIST_INDEX_ADDR(VB_BUF_LAST));
dev_dbg(jpeg_dev->dev, "get resolution: %uX%u, power 0x%x, once_power %u.\n",
width, height, input_signal, jpeg_dev->once_poweroff);
/* The resolution is 640*480 and V4L2_IN_ST_NO_SIGNAL in the case that host is poweroff. */
if (input_signal == HOST_POWER_OFF) {
dev_dbg(jpeg_dev->dev, "Host is poweroff.\n");
jpeg_dev->once_poweroff = true;
return;
}

/* Host machine has never been poweroff since JPEG driver starts running */
if (jpeg_dev->once_poweroff == false) {
input_signal = HAVE_SIGNAL;
phytium_jpeg_write(jpeg_dev, BUF_LIST_INDEX_ADDR(VB_BUF_LAST), HAVE_SIGNAL);
} else if (input_signal == HOST_POWER_ON) {
dev_dbg(jpeg_dev->dev, "No signal on KVM.\n");
return;
}

if ((input_signal == HAVE_SIGNAL && width * height != 0) ||
test_bit(VIDEO_RES_CHANGE, &jpeg_dev->status)) {
jpeg_dev->v4l2_input_status = 0;
dev_dbg(jpeg_dev->dev, "output signal, status 0x%lx.\n", jpeg_dev->status);
}


if (width * height != 0) {
detected_timings->width = width;
detected_timings->height = height;
jpeg_dev->v4l2_input_status = 0;
cur_non_zero = true;
} else {
/* filter some repeated log-print lines */
Expand Down Expand Up @@ -492,11 +514,8 @@ static int phytium_jpeg_query_dv_timings(struct file *file, void *priv,
struct v4l2_dv_timings *timings)
{
int ret;
u32 source_info;
u32 width;
u32 height;
struct phytium_jpeg_dev *jpeg_dev = video_drvdata(file);

u32 input_signal;
/*
* This blocks only if the driver is currently in the process of
* detecting a new resolution; in the event of no signal or timeout
Expand All @@ -516,13 +535,9 @@ static int phytium_jpeg_query_dv_timings(struct file *file, void *priv,
timings->type = V4L2_DV_BT_656_1120;
timings->bt = jpeg_dev->detected_timings;

/* Get resolution from SRC_VGA_INFO_REG */
source_info = phytium_jpeg_read(jpeg_dev, SRC_VGA_INFO_REG);
width = (source_info & SRC_HOR_PIXELS) >> SRC_WIDTH_SHIFT;
height = (source_info & SRC_VER_PIXELS) >> SRC_HEIGHT_SHIFT;

/* Check if that the current resolution is zero. */
if (width == 0 || height == 0)
input_signal = phytium_jpeg_read(jpeg_dev, BUF_LIST_INDEX_ADDR(VB_BUF_LAST));
/* Check if that the power status of the host machine resolution */
if (input_signal != HAVE_SIGNAL)
jpeg_dev->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;

return jpeg_dev->v4l2_input_status ? -ENOLINK : 0;
Expand Down Expand Up @@ -820,8 +835,14 @@ static void phytium_jpeg_resolution_work(struct work_struct *work)
goto done;

phytium_jpeg_init_regs(jpeg_dev);
/* It is evident that the host remains powered on during the
* resolution switch process, so restore the JPEG configuration.
*/
phytium_jpeg_write(jpeg_dev, BUF_LIST_INDEX_ADDR(VB_BUF_LAST), HAVE_SIGNAL);
jpeg_dev->once_poweroff = false;
phytium_jpeg_get_resolution(jpeg_dev);


/* if source's resolution is changed, the event should be enqueued */
if (jpeg_dev->detected_timings.width != jpeg_dev->active_timings.width ||
jpeg_dev->detected_timings.height != jpeg_dev->active_timings.height ||
Expand All @@ -833,7 +854,7 @@ static void phytium_jpeg_resolution_work(struct work_struct *work)
};
v4l2_event_queue(&jpeg_dev->vdev, &event);
clear_bit(VIDEO_FRAME_INPRG, &jpeg_dev->status);
dev_info(jpeg_dev->dev, "event notifies changing resolution\n");
dev_info(jpeg_dev->dev, "event notifies changing resolution.\n");
} else if (test_bit(VIDEO_STREAMING, &jpeg_dev->status)) {
/* No resolution change so just restart streaming */
dev_info(jpeg_dev->dev, "resolution doesn't change\n");
Expand Down Expand Up @@ -1178,7 +1199,7 @@ static int phytium_jpeg_parser_timer30_irq(struct phytium_jpeg_dev *jpeg_dev)
}

ret = devm_request_irq(dev, irq, phytium_jpeg_timer30_irq,
IRQF_TIMER, PHYTIUM_JPEG_NAME, jpeg_dev);
IRQF_TIMER, PHYTIUM_JPEG_NAME, jpeg_dev);
if (ret < 0)
dev_err(dev, "Failed to request timer30 IRQ %d\n", irq);

Expand Down Expand Up @@ -1231,7 +1252,8 @@ static int phytium_jpeg_init(struct phytium_jpeg_dev *jpeg_dev)
dev_err(dev, "Failed to set DMA mask\n");
return ret;
}

/* Initialize the value of buffer_list_address15 register to identify having signal */
phytium_jpeg_write(jpeg_dev, BUF_LIST_INDEX_ADDR(VB_BUF_LAST), HAVE_SIGNAL);
/* Initializing JPEG Y and CbCr quantization table */
phytium_jpeg_init_jpeg_quant(jpeg_dev);

Expand Down Expand Up @@ -1287,6 +1309,7 @@ static int phytium_jpeg_setup_video(struct phytium_jpeg_dev *jpeg_dev)
jpeg_dev->pix_fmt.colorspace = V4L2_COLORSPACE_SRGB; /* maybe ARGB */
jpeg_dev->pix_fmt.quantization = V4L2_QUANTIZATION_FULL_RANGE;
jpeg_dev->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
jpeg_dev->once_poweroff = false;

ret = v4l2_device_register(jpeg_dev->dev, v4l2_dev);
if (ret != 0) {
Expand Down
9 changes: 7 additions & 2 deletions drivers/media/platform/phytium/phytium_jpeg_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,17 @@
#define MAX_PIXEL_CLOCK (1920 * 1080 * 60) /* 1920 x 1080 x 60Hz */

#define SOURCE_RESOLUTION_DETECT_TIMEOUT msecs_to_jiffies(500)
#define RESOLUTION_CHANGE_DELAY msecs_to_jiffies(250)
#define RESOLUTION_CHANGE_DELAY msecs_to_jiffies(150)
#define INVALID_RESOLUTION_DELAY msecs_to_jiffies(250)
#define STOP_TIMEOUT msecs_to_jiffies(1000)

#define INVALID_RESOLUTION_RETRIES 2
#define CAPTURE_BUF_NUMBER 3 /* using how many buffers */
#define VB_BUF_NO 0 /* there are 16 buffer, use which one */
#define VB_BUF_LAST 15 /* Use the last one to identify no signal */
#define HAVE_SIGNAL 0xCDDCDCCD /* VGA output signal */
#define HOST_POWER_ON 0x0 /* Host is poweron */
#define HOST_POWER_OFF 0xDEADBEEF /* Host is poweroff */

/* The below macros are defined for the JPEG header of the phytium JPEG Engine */
#define PHYTIUM_JPEG_HEADER_LEN (256 * 3)
Expand Down Expand Up @@ -123,13 +127,14 @@ struct phytium_jpeg_dev {
unsigned int sequence;
unsigned int max_compressed_size;
struct phytium_jpeg_addr src_addrs[OCM_BUF_NUM];
struct phytium_jpeg_addr dst_addrs[16];
struct phytium_jpeg_addr dst_addrs[VB_BUF_LAST + 1];

bool yuv420;
unsigned int frame_rate;
void __iomem *timer30_addr;
void __iomem *timer31_addr;
struct v4l2_ctrl_handler ctrl_handler;
bool once_poweroff;
};

struct phytium_jpeg_config {
Expand Down
Loading