// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2005-2006 Micronas USA Inc.
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/unistd.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-event.h>
#include <media/videobuf2-vmalloc.h>
#include <media/i2c/saa7115.h>
#include "go7007-priv.h"
#define call_all(dev, o, f, args...) \
v4l2_device_call_until_err(dev, 0, o, f, ##args)
static bool valid_pixelformat(u32 pixelformat)
{
switch (pixelformat) {
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_MPEG1:
case V4L2_PIX_FMT_MPEG2:
case V4L2_PIX_FMT_MPEG4:
return true;
default:
return false;
}
}
static u32 get_frame_type_flag(struct go7007_buffer *vb, int format)
{
u8 *ptr = vb2_plane_vaddr(&vb->vb.vb2_buf, 0);
switch (format) {
case V4L2_PIX_FMT_MJPEG:
return V4L2_BUF_FLAG_KEYFRAME;
case V4L2_PIX_FMT_MPEG4:
switch ((ptr[vb->frame_offset + 4] >> 6) & 0x3) {
case 0:
return V4L2_BUF_FLAG_KEYFRAME;
case 1:
return V4L2_BUF_FLAG_PFRAME;
case 2:
return V4L2_BUF_FLAG_BFRAME;
default:
return 0;
}
case V4L2_PIX_FMT_MPEG1:
case V4L2_PIX_FMT_MPEG2:
switch ((ptr[vb->frame_offset + 5] >> 3) & 0x7) {
case 1:
return V4L2_BUF_FLAG_KEYFRAME;
case 2:
return V4L2_BUF_FLAG_PFRAME;
case 3:
return V4L2_BUF_FLAG_BFRAME;
default:
return 0;
}
}
return 0;
}
static void get_resolution(struct go7007 *go, int *width, int *height)
{
switch (go->standard) {
case GO7007_STD_NTSC:
*width = 720;
*height = 480;
break;
case GO7007_STD_PAL:
*width = 720;
*height = 576;
break;
case GO7007_STD_OTHER:
default:
*width = go->board_info->sensor_width;
*height = go->board_info->sensor_height;
break;
}
}
static void set_formatting(struct go7007 *go)
{
if (go->format == V4L2_PIX_FMT_MJPEG) {
go->pali = 0;
go->aspect_ratio = GO7007_RATIO_1_1;
go->gop_size = 0;
go->ipb = 0;
go->closed_gop = 0;
go->repeat_seqhead = 0;
go->seq_header_enable = 0;
go->gop_header_enable = 0;
go->dvd_mode = 0;
return;
}
switch (go->format) {
case V4L2_PIX_FMT_MPEG1:
go->pali = 0;
break;
default:
case V4L2_PIX_FMT_MPEG2:
go->pali = 0x48;
break;
case V4L2_PIX_FMT_MPEG4:
/* For future reference: this is the list of MPEG4
* profiles that are available, although they are
* untested:
*
* Profile pali
* -------------- ----
* PROFILE_S_L0 0x08
* PROFILE_S_L1 0x01
* PROFILE_S_L2 0x02
* PROFILE_S_L3 0x03
* PROFILE_ARTS_L1 0x91
* PROFILE_ARTS_L2 0x92
* PROFILE_ARTS_L3 0x93
* PROFILE_ARTS_L4 0x94
* PROFILE_AS_L0 0xf0
* PROFILE_AS_L1 0xf1
* PROFILE_AS_L2 0xf2
* PROFILE_AS_L3 0xf3
* PROFILE_AS_L4 0xf4
* PROFILE_AS_L5 0xf5
*/
go->pali = 0xf5;
break;
}
go->gop_size = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_size);
go->closed_gop = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_closure);
go->ipb = v4l2_ctrl_g_ctrl(go->mpeg_video_b_frames) != 0;
go->bitrate = v4l2_ctrl_g_ctrl(go->mpeg_video_bitrate);
go->repeat_seqhead = v4l2_ctrl_g_ctrl(go->mpeg_video_rep_seqheader);
go->gop_header_enable = 1;
go->dvd_mode = 0;
if (go->format == V4L2_PIX_FMT_MPEG2)
go->dvd_mode =
go->bitrate == 9800000 &&
go->gop_size == 15 &&
go->ipb == 0 &&
go->repeat_seqhead == 1 &&